hraness
Theme
Appearance

planted bugs: how to test the tests

a suite that can't catch a bug on purpose catches none by accident

drafted with ai assistance by ben guo

the rest of this lesson is free: add your email to keep reading.

A test suite reports one number: pass or fail. It never reports the number that matters: whether it would have failed on the bug you did not write. Coverage metrics measure which lines executed, not which mistakes would be caught. A suite that cannot catch a bug on purpose will not catch one by accident.

the untested suite

The failure is structural. Every gate in a pipeline is itself code: the assertion, the invariant, the policy check, the admission rule. If the gate is broken (a wrong comparison, an empty check, a variable nobody reads), the suite reports green while guarding nothing. The system then fails in the worst order: silently at the boundary, loudly in production.

Mutation testing inverts the question. Instead of "do the tests pass on correct code," it asks "do the tests fail on deliberately wrong code." A mutant is a seeded defect: flip the comparison, drop the guard, swap the order. If the suite passes anyway, the mutant "survived," and that survival is a measured hole in the tests.

what a mutant is

The mutants that matter are not random syntax noise; they are planted bugs shaped like real mistakes. In the portfolio they show up in three forms:

Mutant specs and models. vhalla runs its TLA+ specifications against deliberately wrong protocol variants to prove the spec can actually fail. A spec that never rejects a mutant is asserting a property too weak to catch the bug class it exists for.

Boundary mutants. Gobstopper's admission and boundary checks get seeded defects: the policy that admits only the correct shape is run against a version of the check with the condition inverted or the bound removed, and the suite must catch the inversion.

Field mutations. ALGAL's contract tests mutate manifest fields: swap a bound, drop a required field, widen a capability, and confirm the admission layer rejects exactly those changes. The mutants pin the admission semantics rather than the happy path.

where the mutants live

The convention is to keep mutants inside the test suite, not in a separate tool run occasionally. A mutant harness writes the defective variant (a patched config, a flipped flag, a wrong constant), runs the suite or the specific check against it, and asserts failure. The test is then a proof that the gate's guard is load-bearing, not decorative.

The yield is precise: every surviving mutant names a place where wrong code would pass review. Every killed mutant is evidence the gate catches that class. The suite's coverage stops being "lines executed" and becomes "mistakes provably caught."

the honest limits

Mutants measure the suite, not the system. A perfectly killed mutation suite proves the tests catch the mutant classes you planted; bugs outside those classes are still invisible. The technique is a check on test quality, not a substitute for the other evidence in this series.

Mutants also only exist where someone thought to plant them. The failure mode mirrors property testing: a mutant space that covers easy flips (off-by-one, inverted booleans) and misses the interesting mutations (wrong order of operations, missing fsync, dropped bounds) measures the easy holes and leaves the deep ones unmeasured. The fix is the same fix everywhere: plant mutants at the boundaries where the system actually fails, and name the space in the test.

The last limit is cost and interpretation. A mutant suite that takes longer than the tests themselves gets skipped, and a surviving mutant is a finding to triage, not a verdict: some survivors are equivalent mutants (the flip does not change semantics), and dismissing them needs judgment. Kept small and pointed at real boundaries, though, the mutant suite is the cheapest way to answer the question every green build should answer: would this suite have caught the bug that matters?

keep reading: free for subscribers

the rest of this lesson is free. enter your email to subscribe, and every subscriber lesson unlocks in this browser.

already subscribed? enter the same email to unlock.