Mutation Testing
A technique to evaluate test quality by introducing small changes (mutations) to code and checking if tests detect them. Undetected mutations indicate weak tests.
Definition
Mutation testing creates "mutants" — copies of code with small changes like flipping operators (> to <), removing statements, or changing return values. Good tests should fail when running against mutants ("kill" them). Surviving mutants reveal gaps in test coverage or assertions. Tools include Stryker (JavaScript/TypeScript), PIT (Java), and mutmut (Python). Mutation score = killed mutants / total mutants.
Why It Matters
Code coverage can be high while tests are still weak (e.g., tests that exercise code without asserting outcomes). Mutation testing measures actual test effectiveness. Research shows mutation testing finds 2-4x more defects than coverage-based testing. It's computationally expensive but valuable for critical code.
Example
Code: if (age >= 18) return true. A mutant changes >= to >. If tests don't catch this (all test users are >18, none exactly 18), the mutant survives, revealing missing edge case test.