变异测试通过故意在代码中引入小的缺陷("mutants")并检查测试是否捕获它们,来评估测试套件的质量。它衡量的是测试实际上有多好地检测缺陷——超越了仅测量执行的覆盖率。
变异测试如何工作
text
1. A tool makes small changes (MUTATIONS) to the code, e.g.:
→ change + to -, > to >=, true to false, remove a statement, change a constant
→ each mutation = a deliberate "bug" (a MUTANT version of the code)
2. Run the TEST SUITE against each mutant:
→ tests FAIL → the mutant is "KILLED" (good — tests caught the bug) ✓
→ tests PASS → the mutant "SURVIVED" (bad — tests DIDN'T catch the bug) ✗
3. MUTATION SCORE = % of mutants killed → measures how good the tests are at catching bugs
为什么比覆盖率更好
text
COVERAGE → measures if code was EXECUTED (not if behavior was verified) → can be high with
weak tests (no real assertions)
MUTATION TESTING → measures if tests actually DETECT bugs (changes in behavior):
→ a surviving mutant reveals a GAP — tests execute that code but don't verify it well
(weak/missing assertions, untested behavior)
→ A much stronger signal of TEST QUALITY than coverage.
注意事项
text
✓ Reveals weak tests (high coverage but surviving mutants = false confidence)
⚠️ COMPUTATIONALLY EXPENSIVE (runs the suite many times — once per mutant) → slow
⚠️ "Equivalent mutants" (mutations that don't change behavior) → false survivors to ignore
→ Tools: Stryker (JS), PIT (Java), mutmut (Python). Use on critical code; run periodically.
为什么这很重要
理解变异测试是有价值的高级知识,因为它提供了远强于覆盖率的测试质量度量,解决了覆盖率的关键弱点,因此对于评估和改进测试套件很有用。
根本的洞察是覆盖率衡量执行,而非验证——代码可以被测试
