mcpField
M
mutation-testing

mutation-testing

github.com/proffesor-for-testing测试与质量520117 次安装今天更新
代码仓库

关于 mutation-testing

mutation-testing 是评估和改进测试有效性的实践指南,适合希望确认测试能否发现缺陷的开发者。它介绍变异、测试执行、存活变异分析,并涵盖 Stryker 和 Agent 驱动的流程。

主要功能

  1. 01通过代码变异检验测试
  2. 02计算变异分数
  3. 03定位存活变异
  4. 04介绍 Stryker 配置与运行
  5. 05支持 Agent 驱动分析

适用场景

  1. 01评估测试套件质量
  2. 02发现断言覆盖缺口
  3. 03发布前验证关键路径
  4. 04针对存活变异补充测试

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/proffesor-for-testing/agentic-qe --skill mutation-testing

安装后在 Claude Code 中输入/mutation-testing确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

config.json
run-history.json
evals/
mutation-testing.yaml
references/
mutation-operators.md
schemas/
output.json
scripts/
validate-config.json
test-data/
sample-output.json

详细介绍

变异测试

<default_to_action> 在验证测试质量或提升测试效果时:

  1. 对代码进行变异(将 + 改为 -,将 >= 改为 >,删除语句)
  2. 针对每个变异体运行测试
  3. 验证测试能捕获变异(杀死变异体)
  4. 找出存活的变异体(测试需要改进)
  5. 加强测试,杀死存活的变异体

快速变异指标:

  • 变异得分 = 已杀死的变异体 /(已杀死的变异体 + 存活的变异体)
  • 目标:变异得分 > 80%
  • 存活的变异体 = 测试较弱

成功的关键因素:

  • 高覆盖率 ≠ 好测试(100% 覆盖率,0% 断言)
  • 变异测试可证明测试确实能捕获 Bug
  • 优先关注关键代码路径 </default_to_action>

快速参考卡

适用场景
  • 评估测试套件质量
  • 发现测试断言中的缺口
  • 证明测试能捕获 Bug
  • 重要版本发布前
变异得分解读
得分解读
90%+测试质量极佳
80-90%良好,只需少量改进
60-80%需要关注
< 60%存在明显缺口
常见变异操作符
类别原始代码变异体
算术a + ba - b
关系x >= 18x > 18
逻辑a && ba || b
条件if (x)if (true)
语句return x(已删除)

变异测试的工作原理

// 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 value

使用 Stryker

# Install
npm install --save-dev @stryker-mutator/core @stryker-mutator/jest-runner

# Initialize
npx stryker init

配置:

{
  "packageManager": "npm",
  "reporters": ["html", "clear-text", "progress"],
  "testRunner": "jest",
  "coverageAnalysis": "perTest",
  "mutate": [
    "src/**/*.ts",
    "!src/**/*.spec.ts"
  ],
  "thresholds": {
    "high": 90,
    "low": 70,
    "break": 60
  }
}

运行:

npx stryker run

输出:

Mutation Score: 87.3%
Killed: 124
Survived: 18
No Coverage: 3
Timeout: 1

修复存活的变异体

// 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 驱动的变异测试

// 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 协作提示

记忆命名空间
aqe/mutation-testing/
├── mutation-results/*   - Stryker reports
├── surviving/*          - Surviving mutants
├── generated-tests/*    - Tests to kill mutants
└── trends/*             - Mutation score over time
集群协作
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'
});

相关技能


请记住

高代码覆盖率 ≠ 好测试。 100% 覆盖率但断言薄弱 = 毫无用处。变异测试可证明测试确实能捕获 Bug。

优先关注关键路径。 不要对所有内容都进行变异测试——优先测试支付、身份验证和数据完整性相关代码。

使用 Agent: Agent 会运行变异分析、找出存活的变异体,并生成缺失的测试用例来杀死它们,从而自动提升测试质量。

运行历史

每次运行变异测试后,将结果追加到此技能目录中的 run-history.json:

node -e "
const fs = require('fs');
const h = JSON.parse(fs.readFileSync('.claude/skills/mutation-testing/run-history.json'));
h.runs.push({date: new Date().toISOString().split('T')[0], mutation_score_pct: SCORE, killed: KILLED, survived: SURVIVED});
fs.writeFileSync('.claude/skills/mutation-testing/run-history.json', JSON.stringify(h, null, 2));
"

每次运行前读取 run-history.json,以跟踪得分随时间的变化。

技能组合

  • 变异测试前 → 运行 /qe-test-generation,确保已有测试
  • 获得变异测试结果后 → 使用 /qe-coverage-analysis,确定改进方向的优先级
  • 质量门禁 → 将结果提供给 /qe-quality-assessment,以决定是否发布

注意事项

  • 如果同时安装了 jest 和 vitest,Stryker 需要显式指定 --testRunner jest
  • 将日期比较中的 >= 变异为 > 通常不会被杀死——添加边界测试
  • 在超过 500 LOC 的文件上运行会超时;使用 --mutate 指定目标函数
  • --concurrency 默认值为 CPU 数量,在容器中可能导致内存溢出——将其设为 2

评论

支持 Markdown