2026-06-30 20:45:25 +02:00

80 lines
3.3 KiB
Markdown

---
name: test-focus-isolation
description: 'Refactor tests so each one fails for only one reason and asserts one conceptual behavior. Use when: reviewing/refactoring tests with overlapping assertions, duplicate checks, or tests that verify the same behavior as another test.'
---
# Test Focus Isolation
## When to Use
- Two or more tests assert the same outcome (e.g., both check Cola delivery)
- A test mixes assertions about different conceptual behaviors
- A failure could break multiple tests for the same root cause
- Reviewing test coverage and finding overlapping checks
## Principles
### 1. One Reason to Fail Per Test
Each test should fail for **exactly one root cause**. If the same assertion appears in multiple tests, a single bug breaks multiple tests — this wastes debugging time and reduces signal quality.
**Rule**: A specific behavior or assertion should appear in exactly **one** test.
**✗ Bad** — Both tests fail if Cola delivery breaks:
```cpp
TEST_F(suite, cola_delivery) {
EXPECT_EQ(vm.deliver(Choice::Cola), Brand::Coke);
}
TEST_F(suite, multiple_choices) {
EXPECT_EQ(vm.deliver(Choice::Cola), Brand::Coke); // ← duplicate
EXPECT_EQ(vm.deliver(Choice::FizzyOrange), Brand::Fanta);
}
```
**✓ Good** — Each behavior is tested once:
```cpp
TEST_F(suite, cola_delivery) {
EXPECT_EQ(vm.deliver(Choice::Cola), Brand::Coke);
}
TEST_F(suite, multiple_choices) {
// Only the NEW behavior this test introduces
EXPECT_EQ(vm.deliver(Choice::FizzyOrange), Brand::Fanta);
}
```
### 2. One Conceptual Assert Per Test
A test should verify **one conceptual behavior**. If a test checks two different things (e.g., Cola delivery AND FizzyOrange delivery), split it into two tests — unless the concept being tested is specifically "multiple choices work together."
**Rule**: Each test name should answer "yes/no" to a single question. The assertions inside should all serve that same question.
**✗ Bad** — Two behaviors in one test:
```cpp
TEST_F(suite, processes_orders) {
EXPECT_EQ(vm.deliver(Choice::Cola), Brand::Coke);
EXPECT_EQ(vm.deliver(Choice::FizzyOrange), Brand::Fanta);
}
```
**✓ Good** — Each test asks one question:
```cpp
TEST_F(suite, delivers_cola) {
EXPECT_EQ(vm.deliver(Choice::Cola), Brand::Coke);
}
TEST_F(suite, delivers_fizzy_orange) {
EXPECT_EQ(vm.deliver(Choice::FizzyOrange), Brand::Fanta);
}
```
**Exception**: If the concept being tested inherently involves multiple values (e.g., "supports multiple choices simultaneously"), it's acceptable to check all of them — because the test name communicates the multi-behavior concept.
## Procedure
1. **Scan tests for overlapping assertions** — grep for repeated `EXPECT_EQ`, `EXPECT_TRUE`, etc. across tests in the same suite.
2. **Identify the unique behavior** each test introduces — what does this test verify that no other test verifies?
3. **Remove duplicate assertions** — keep the assertion only in the test that best owns it. Delete it from the others.
4. **Rename tests** to clearly describe their singular behavior (e.g., `delivers_cola` instead of `configured_choice_delivers_correct_can`).
5. **Split tests** if a single test asserts multiple unrelated behaviors (unless the concept is multi-behavior by nature).
6. **Verify** — run the test suite to ensure coverage is preserved and tests pass.