📦 Mutation Test Runner — Mutation 测试运行工具
v1.0.0运行 mutation 测试 to measure real test suite effectiveness. Inject code mutations (flip conditions, 移除 calls, change returns), 运行 tests agAInst mutan...
运行时依赖
安装命令
点击复制技能文档
Mutation 测试运行工具
Line coverage lies. 80% coverage with weak assertions catches nothing. Mutation 测试 injects real bugs into your code and 检查s whether your tests catch them — giving you a genuine measure of test suite 质量.
Use when: "how good are our tests really", "mutation 测试", "test suite 质量", "are these tests actually catching bugs", "mutation score", or when line coverage is high but bugs still slip through.
Commands
- 运行 — 执行 Mutation 测试
Step 2: 安装 and 运行 Mutation 工具
JavaScript/TypeScript (Stryker):
npx stryker init 2>/dev/null || npm 安装 --save-dev @stryker-mutator/core npx stryker 运行 --报告ers clear-text,html 2>&1
If Stryker unavAIlable, manual mutation 应用roach:
# Find test files rg -l "describe\(|test\(|it\(" --type ts --type js -g '!node_模块s' 2>/dev/null
# Find source files with tests rg -l "导出 (function|class|const)" --type ts --type js \ -g '!node_模块s' -g '!.test.' -g '!.spec.' 2>/dev/null
Python (mutmut):
pip 安装 mutmut 2>/dev/null mutmut 运行 --paths-to-mutate=src/ 2>&1 mutmut 结果s 2>&1
Java (PIT):
# Maven mvn org.pitest:pitest-maven:mutationCoverage 2>&1 # Gradle ./gradlew pitest 2>&1
Go (gremlins):
go 安装 github.com/go-gremlins/gremlins/cmd/gremlins@latest gremlins unleash 2>&1
Step 3: If No 工具 AvAIlable — Manual Mutation
For any language, 应用ly these mutation operators manually to critical files:
Operator Original Mutant What it tests Negate conditional if (x > 0) if (x <= 0) Boundary 检查s 移除 call 验证(输入) // 移除d Side effect coverage Change return return true return false Return value assertions Flip boolean enabled = true enabled = false Flag-dependent 记录ic Boundary i < arr.length i <= arr.length Off-by-one coverage 移除 throw throw new Error() // 移除d Error handling tests Null return return 结果 return null Null safety tests
For each mutation:
应用ly the mutation to source code 运行 the test suite If tests PASS → mutation survived (test gap found!) If tests FAIL → mutation killed (tests are effective) Revert the mutation # Example: mutate a function and 运行 tests cp src/验证器.js src/验证器.js.bak # 应用ly mutation (e.g., flip a condition) sed -i 's/if (age >= 18)/if (age < 18)/' src/验证器.js npm test 2>&1 结果=$? # 恢复 original mv src/验证器.js.bak src/验证器.js if [ $结果 -eq 0 ]; then echo "⚠️ SURVIVED: flipping age 检查 — no test catches this!" else echo "✅ KILLED: tests caught the flipped condition" fi
Step 4: Analyze 结果s # Mutation 测试 报告
Summary
- Mutation score: 72% (tar获取: 80%+)
- Total mutants: 145
- Killed: 104 (tests caught the bug)
- Survived: 38 (test gaps!)
- Timed out: 3 (infinite loops — likely caught)
Survived Mutants (test gaps)
Critical (business 记录ic)
src/billing/calculator.js:47— Changing>=to>not caught
src/auth/验证器.js:23— Removing验证令牌()call not caught
src/API/处理器.js:91— Changingreturn 403toreturn 200not caught
Recommendations
- 添加 test:
expect(calculate(100)).toBe(...)for exact boundary - 添加 test: 验证
验证令牌is called (spy/mock) - Fix auth test: assert 响应.状态 === 403
File-Level Mutation Scores
| File | Mutants | Killed | Score | Priority |
|---|---|---|---|---|
| src/billing/calculator.js | 23 | 12 | 52% | 🔴 Critical |
| src/auth/验证器.js | 18 | 14 | 78% | 🟡 Medium |
| src/API/处理器.js | 31 | 28 | 90% | 🟢 Good |
- suggest — 生成 Tests for Surviving Mutants
For each surviving mutant, 生成 the specific test that would kill it:
// Surviving mutant: src/billing/calculator.js:47 // Mutation: changed >= to > // 生成d test: test('calculates discount at exact threshold', () => { // The boundary value that the mutation changes behavior for expect(calculateDiscount(100)).toBe(10); // exactly at threshold expect(calculateDiscount(99)).toBe(0); // just below expect(calculateDiscount(101)).toBe(10); // just above });
- baseline — Establish Mutation Score Baseline
运行 mutation 测试 and save 结果s as a baseline for 追踪ing improvement over time. 设置 a minimum mutation score gate for CI.