What is mutation testing?
Mutation testing measures test suite quality by deliberately introducing small code changes (mutations) and checking whether existing tests catch them. Unlike code coverage, which only tracks which lines ran, mutation testing reveals whether assertions would actually detect a defect. The process generates mutants via operators like relational replacements or boolean flips, runs the test suite against each, and reports a mutation score based on how many were killed. A practical JavaScript example using Stryker and Mocha shows how 100% line coverage can still leave two surviving mutants. The post covers mutation states (killed, survived, equivalent, timeout), common mutation operators, language-specific tools (Stryker, PIT, mutmut, Gremlins), and CI/CD integration strategies including scoped diff-mode runs, parallelization, scheduled full runs, and threshold-based build failures. Limitations include high compute cost, unavoidable equivalent mutants, and the fact that 100% mutation score doesn't guarantee correctness.