4 bad Practices in Software Testing
Testing is the backbone of reliable software. But even when tests exist, bad testing practices can lead to flaky builds, false confidence…
4 bad Practices in Software Testing
Testing is the backbone of reliable software. But even when tests exist, bad testing practices can lead to flaky builds, false confidence, and nightmarish debugging sessions. Below are some of the most common (and costly) mistakes developers make — plus better alternatives.
🧪 1. Overusing Factories
What’s wrong: Factories are great for setting up complex test data, but over-relying on them — especially when the factory creates more than what’s needed — adds noise and slows your tests. It becomes hard to understand what the test is really checking.
Why it’s bad:
- Hidden dependencies
- Slower test execution
- Harder to read and debug tests
Better approach: Use minimal, explicit test data. Consider writing simple builders or plain objects that only include what’s relevant to that test case.
Bad example:
@Test
void testUserIsActive() {
User user = UserFactory.create(); // Factory adds unnecessary fields like address, email, etc.
assertTrue(user.isActive());
}
Why it’s bad: The test uses a full-blown object with irrelevant data. That can hide bugs or cause false failures when unrelated parts change.
Better approach:
@Test
void testUserIsActive() {
User user = new User("john", true);
assertTrue(user.isActive());
}
Use simple, focused test data. Factories are okay, but don’t rely on them blindly.
🎲 2. Using Random Inputs in Tests
What’s wrong: Adding randomness to your tests might sound like a good way to improve coverage, but it often leads to non-deterministic tests — tests that pass or fail depending on chance.
Why it’s bad:
- Flaky CI builds
- Hard to reproduce bugs
- Trust in test suite decreases
Better approach: Keep inputs predictable and deterministic.
Bad example:
@Test
void testDiscountIsPositive() {
double price = Math.random() * 100;
double discount = calculateDiscount(price);
assertTrue(discount >= 0);
}
Why it’s bad: This test might pass 99 times and fail once. And when it fails, you won’t know why.
Better approach (predictable input):
@Test
void testDiscountForFixedPrice() {
double price = 50.0;
double discount = calculateDiscount(price);
assertEquals(5.0, discount); // assuming 10%
}
For randomness-based logic, consider parameterized tests with fixed values.
🚫 3. Not Having Tests at All
What’s wrong: This one’s obvious, yet still common. Many teams delay testing in early stages or skip it entirely to “save time.” It might feel faster at first, but it leads to technical debt, fragile code, and a fear of changing anything.
Why it’s bad:
- Bugs go unnoticed
- Slower feature delivery in the long run
- Difficult to refactor or onboard new devs
Better approach: Adopt a “test as you go” mindset. Even basic unit tests for core logic and integration tests for critical paths can go a long way.
This one, we skip examples.
🧨 4. Tests That Affect Other Tests
What’s wrong: When tests rely on shared state or don’t clean up after themselves, they can cause unexpected side effects in other tests.
Why it’s bad:
- Tests pass or fail depending on run order
- Time-consuming debugging
- Hidden coupling between test cases
Better approach: Ensure each test is independent and isolated. Use fresh instances, mock dependencies where needed, and reset state (e.g., databases, files, caches) between tests.
Bad example:
static List<String> globalList = new ArrayList<>();
@Test
void testAddItem() {
globalList.add("item1");
assertEquals(1, globalList.size());
}
@Test
void testListShouldBeEmpty() {
assertEquals(0, globalList.size()); // fails if testAddItem runs first
}
Why it’s bad: Tests should not depend on run order. Shared state causes unpredictable failures.
Better approach:
private List<String> list;
@BeforeEach
void setup() {
list = new ArrayList<>();
}
@Test
void testAddItem() {
list.add("item1");
assertEquals(1, list.size());
}
@Test
void testListIsInitiallyEmpty() {
assertEquals(0, list.size());
}
Always reset state in @BeforeEach or use dependency injection to isolate test data.
Final Thoughts
Writing tests is not enough — writing good tests matters. Avoiding these bad practices helps keep your test suite:
- Reliable
- Fast
- Easy to maintain
- And most importantly, trustworthy
Testing isn’t just a dev task — it’s an investment in software quality.
💬 What would you add to this list?
Let me know your thoughts or horror stories from test suites gone wrong 👇
메타데이터
- post_id
- 79e7f1be5437
- slug
- 4-bad-practices-in-software-testing-79e7f1be5437
- url
- https://medium.com/@odevpoliglota/4-bad-practices-in-software-testing-79e7f1be5437
- canonical_url
- https://medium.com/@odevpoliglota/4-bad-practices-in-software-testing-79e7f1be5437
- author_url
- https://medium.com/@odevpoliglota
- status
- ok
- fetched_at
- 2026-06-26 06:47:43