mutation-testing
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseMutation Testing
突变测试
<default_to_action>
When validating test quality or improving test effectiveness:
- MUTATE code (change + to -, >= to >, remove statements)
- RUN tests against each mutant
- VERIFY tests catch mutations (kill mutants)
- IDENTIFY surviving mutants (tests need improvement)
- STRENGTHEN tests to kill surviving mutants
Quick Mutation Metrics:
- Mutation Score = Killed / (Killed + Survived)
- Target: > 80% mutation score
- Surviving mutants = weak tests
Critical Success Factors:
- High coverage ≠ good tests (100% coverage, 0% assertions)
- Mutation testing proves tests actually catch bugs
- Focus on critical code paths first </default_to_action>
<default_to_action>
在验证测试质量或提升测试有效性时:
- 对代码进行突变(将+改为-,>=改为>,移除语句等)
- 针对每个突变体运行测试
- 验证测试是否能捕获突变(杀死突变体)
- 识别存活的突变体(对应的测试需要改进)
- 强化测试以杀死存活的突变体
快速突变指标:
- 突变分数 = 被杀死的突变体数量 / (被杀死的突变体数量 + 存活的突变体数量)
- 目标:突变分数 > 80%
- 存活的突变体 = 薄弱的测试
关键成功要素:
- 高覆盖率 ≠ 优质测试(100%覆盖率但0%断言)
- 突变测试可证明测试确实能发现漏洞
- 优先关注关键代码路径 </default_to_action>
Quick Reference Card
快速参考卡
When to Use
使用场景
- Evaluating test suite quality
- Finding gaps in test assertions
- Proving tests catch bugs
- Before critical releases
- 评估测试套件质量
- 发现测试断言中的漏洞
- 证明测试能发现漏洞
- 关键版本发布前
Mutation Score Interpretation
突变分数解读
| Score | Interpretation |
|---|---|
| 90%+ | Excellent test quality |
| 80-90% | Good, minor improvements |
| 60-80% | Needs attention |
| < 60% | Significant gaps |
| 分数 | 解读 |
|---|---|
| 90%+ | 测试质量极佳 |
| 80-90% | 良好,需小幅改进 |
| 60-80% | 需要关注 |
| < 60% | 存在重大漏洞 |
Common Mutation Operators
常见突变操作符
| Category | Original | Mutant |
|---|---|---|
| Arithmetic | | |
| Relational | | |
| Logical | | |
| Conditional | | |
| Statement | | (removed) |
| 类别 | 原代码 | 突变体 |
|---|---|---|
| 算术运算 | | |
| 关系运算 | | |
| 逻辑运算 | | |
| 条件判断 | | |
| 语句移除 | | (已移除) |
How Mutation Testing Works
突变测试的工作原理
javascript
// Original code
function isAdult(age) {
return age >= 18; // ← Mutant: change >= to >
}
// Strong test (catches mutation)
test('18 is adult', () => {
expect(isAdult(18)).toBe(true); // Kills mutant!
});
// Weak test (mutation survives)
test('19 is adult', () => {
expect(isAdult(19)).toBe(true); // Doesn't catch >= vs >
});
// Surviving mutant → Test needs boundary valuejavascript
// Original code
function isAdult(age) {
return age >= 18; // ← Mutant: change >= to >
}
// Strong test (catches mutation)
test('18 is adult', () => {
expect(isAdult(18)).toBe(true); // Kills mutant!
});
// Weak test (mutation survives)
test('19 is adult', () => {
expect(isAdult(19)).toBe(true); // Doesn't catch >= vs >
});
// Surviving mutant → Test needs boundary valueUsing Stryker
使用Stryker
bash
undefinedbash
undefinedInstall
Install
npm install --save-dev @stryker-mutator/core @stryker-mutator/jest-runner
npm install --save-dev @stryker-mutator/core @stryker-mutator/jest-runner
Initialize
Initialize
npx stryker init
**Configuration:**
```json
{
"packageManager": "npm",
"reporters": ["html", "clear-text", "progress"],
"testRunner": "jest",
"coverageAnalysis": "perTest",
"mutate": [
"src/**/*.ts",
"!src/**/*.spec.ts"
],
"thresholds": {
"high": 90,
"low": 70,
"break": 60
}
}Run:
bash
npx stryker runOutput:
Mutation Score: 87.3%
Killed: 124
Survived: 18
No Coverage: 3
Timeout: 1npx stryker init
**配置:**
```json
{
"packageManager": "npm",
"reporters": ["html", "clear-text", "progress"],
"testRunner": "jest",
"coverageAnalysis": "perTest",
"mutate": [
"src/**/*.ts",
"!src/**/*.spec.ts"
],
"thresholds": {
"high": 90,
"low": 70,
"break": 60
}
}运行:
bash
npx stryker run输出:
Mutation Score: 87.3%
Killed: 124
Survived: 18
No Coverage: 3
Timeout: 1Fixing Surviving Mutants
修复存活的突变体
javascript
// Surviving mutant: >= changed to >
function calculateDiscount(quantity) {
if (quantity >= 10) { // Mutant survives!
return 0.1;
}
return 0;
}
// Original weak test
test('large order gets discount', () => {
expect(calculateDiscount(15)).toBe(0.1); // Doesn't test boundary
});
// Fixed: Add boundary test
test('exactly 10 gets discount', () => {
expect(calculateDiscount(10)).toBe(0.1); // Kills mutant!
});
test('9 does not get discount', () => {
expect(calculateDiscount(9)).toBe(0); // Tests below boundary
});javascript
// Surviving mutant: >= changed to >
function calculateDiscount(quantity) {
if (quantity >= 10) { // Mutant survives!
return 0.1;
}
return 0;
}
// Original weak test
test('large order gets discount', () => {
expect(calculateDiscount(15)).toBe(0.1); // Doesn't test boundary
});
// Fixed: Add boundary test
test('exactly 10 gets discount', () => {
expect(calculateDiscount(10)).toBe(0.1); // Kills mutant!
});
test('9 does not get discount', () => {
expect(calculateDiscount(9)).toBe(0); // Tests below boundary
});Agent-Driven Mutation Testing
Agent驱动的突变测试
typescript
// Analyze mutation score and generate fixes
await Task("Mutation Analysis", {
targetFile: 'src/payment.ts',
generateMissingTests: true,
minScore: 80
}, "qe-test-generator");
// Returns:
// {
// mutationScore: 0.65,
// survivedMutations: [
// { line: 45, operator: '>=', mutant: '>', killedBy: null }
// ],
// generatedTests: [
// 'test for boundary at line 45'
// ]
// }
// Coverage + mutation correlation
await Task("Coverage Quality Analysis", {
coverageData: coverageReport,
mutationData: mutationReport,
identifyWeakCoverage: true
}, "qe-coverage-analyzer");typescript
// Analyze mutation score and generate fixes
await Task("Mutation Analysis", {
targetFile: 'src/payment.ts',
generateMissingTests: true,
minScore: 80
}, "qe-test-generator");
// Returns:
// {
// mutationScore: 0.65,
// survivedMutations: [
// { line: 45, operator: '>=', mutant: '>', killedBy: null }
// ],
// generatedTests: [
// 'test for boundary at line 45'
// ]
// }
// Coverage + mutation correlation
await Task("Coverage Quality Analysis", {
coverageData: coverageReport,
mutationData: mutationReport,
identifyWeakCoverage: true
}, "qe-coverage-analyzer");Agent Coordination Hints
Agent协作提示
Memory Namespace
内存命名空间
aqe/mutation-testing/
├── mutation-results/* - Stryker reports
├── surviving/* - Surviving mutants
├── generated-tests/* - Tests to kill mutants
└── trends/* - Mutation score over timeaqe/mutation-testing/
├── mutation-results/* - Stryker reports
├── surviving/* - Surviving mutants
├── generated-tests/* - Tests to kill mutants
└── trends/* - Mutation score over timeFleet Coordination
集群协作
typescript
const mutationFleet = await FleetManager.coordinate({
strategy: 'mutation-testing',
agents: [
'qe-test-generator', // Generate tests for survivors
'qe-coverage-analyzer', // Coverage correlation
'qe-quality-analyzer' // Quality assessment
],
topology: 'sequential'
});typescript
const mutationFleet = await FleetManager.coordinate({
strategy: 'mutation-testing',
agents: [
'qe-test-generator', // Generate tests for survivors
'qe-coverage-analyzer', // Coverage correlation
'qe-quality-analyzer' // Quality assessment
],
topology: 'sequential'
});Related Skills
相关技能
- tdd-london-chicago - Write effective tests first
- test-design-techniques - Boundary value analysis
- quality-metrics - Measure test effectiveness
- tdd-london-chicago - 先编写有效的测试
- test-design-techniques - 边界值分析
- quality-metrics - 评估测试有效性
Remember
注意事项
High code coverage ≠ good tests. 100% coverage but weak assertions = useless. Mutation testing proves tests actually catch bugs.
Focus on critical paths first. Don't mutation test everything - prioritize payment, authentication, data integrity code.
With Agents: Agents run mutation analysis, identify surviving mutants, and generate missing test cases to kill them. Automated improvement of test quality.
高代码覆盖率 ≠ 优质测试。100%覆盖率但断言薄弱的测试毫无用处。突变测试可证明测试确实能发现漏洞。
优先关注关键路径。无需对所有代码进行突变测试,优先处理支付、认证、数据完整性相关代码。
借助Agent: Agent可运行突变分析、识别存活的突变体,并生成缺失的测试用例来杀死它们,实现测试质量的自动化提升。