Test Coverage Types
debt(d5/e3/b5/t9)
Closest to 'specialist tool catches it' (d5). The detection_hints.tools list includes phpunit, xdebug, pcov, and infection — these are specialist tools that must be explicitly configured and run. The problem (tests that execute but don't assert, branches not covered, no mutation testing) is not caught by a compiler or default linter; it requires running coverage reports and mutation testing tooling like Infection PHP. Slightly aligned to d5 because coverage and mutation tools are available but non-default and require deliberate setup.
Closest to 'simple parameterised fix' (e3). The quick_fix states switching from line coverage to branch coverage as the primary metric and adding mutation testing. This is a configuration and process change — updating phpunit/xdebug configuration, adjusting CI thresholds, and adding Infection PHP. It's more than a single-line patch (not e1) but is largely localised to CI configuration and test suite setup rather than touching multiple application files, placing it at e3.
Closest to 'persistent productivity tax' (b5). The misconception and common_mistakes indicate that once a team adopts 100% line coverage as the sole metric, it shapes every testing decision going forward — developers write coverage-padding tests instead of meaningful ones. This applies across web, cli, and queue-worker contexts (broad applies_to). It slows down many work streams by creating false confidence and technical debt in the test suite, but it doesn't define the entire system architecture, placing it at b5.
Closest to 'catastrophic trap — the obvious way is always wrong' (t9). The misconception field states explicitly: '100% code coverage means the code is fully tested.' This is the canonical, nearly universal wrong belief. The why_it_matters confirms teams targeting 100% line coverage have false confidence providing zero protection against regressions. The obvious, intuitive interpretation of '100% coverage' directly contradicts the actual safety guarantee. This is a textbook t9: the natural, competent reading of the metric is always misleading.
Also Known As
TL;DR
Explanation
Line coverage: percentage of source lines executed by tests — easiest to achieve, easiest to game (execute a line without asserting its output). Branch coverage: percentage of if/else/switch branches taken — more meaningful than line coverage. Mutation testing (Infection PHP): automatically modifies code (change + to -, flip conditions) and checks if tests fail — the mutation score reveals whether tests actually detect changes. 100% line coverage with no assertions = 100% line coverage, 0% mutation score.
Common Misconception
Why It Matters
Common Mistakes
- 100% line coverage as the only quality metric
- Tests that cover code without asserting outcomes
- Testing implementation details instead of observable behaviour
- Not running mutation testing on critical business logic paths
Code Examples
// 100% line coverage, 0% useful assertions:
public function testCalculateTotal(): void {
$cart = new Cart();
$cart->add(new Item('Widget', 9.99));
$total = $cart->calculateTotal();
// No assertion — executes the code but checks nothing!
$this->assertTrue(true); // 100% line coverage, 0% mutation score
}
// Meaningful coverage with real assertions:
public function testCalculateTotalAppliesVat(): void {
$cart = new Cart(new VatCalculator(0.20));
$cart->add(new Item('Widget', 10.00));
$this->assertSame(12.00, $cart->calculateTotal(), '20% VAT not applied');
}
// Run mutation testing:
// vendor/bin/infection --min-msi=80 --min-covered-msi=90