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

3.3 KiB

name, description
name description
test-focus-isolation 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:

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:

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:

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:

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.