关于 mutation-testing
mutation-testing 是一项指导 Agent 执行变异测试的技能,适用于将测试质量检查纳入 PR 前流程的开发团队。它依据项目类型选择工具,并通过变异存活情况检查测试覆盖的行为是否充分。
主要功能
- 01按项目标记选择变异测试工具
- 02将测试范围限定在相关代码
- 03汇总变异数量、存活数与得分
- 04按场景检查存活变异
- 05未达到 100% 时阻止默认 PR 流程
适用场景
- 01在创建 PR 前验证测试能否捕获缺陷
- 02定位未被测试发现的代码变更
- 03为存活变异关联场景并提出测试建议
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ jwilger/ agent-skills --skill mutation-testing安装后在 Claude Code 中输入/mutation-testing确认已加载。
详细介绍
突变测试
**价值:**反馈——突变测试通过证明测试确实能检测到它们声称可以防止的错误,从而闭合验证环。没有突变测试,通过的测试可能会带来虚假的信心。
目的
教会 Agent 在创建 PR 前,将突变测试作为质量门禁。突变测试会对生产代码做小幅修改(突变),并检查测试能否捕获这些修改。未被检测到的突变体揭示了可能让错误逃过检测的测试缺口。要求突变杀死率达到 100%。
实践
检测并运行合适的工具
检测项目类型并运行相应的突变测试工具。
-
检查项目标记:
Cargo.toml-> Rust ->cargo mutantspackage.json-> TypeScript/JavaScript ->npx stryker runpyproject.toml或setup.py-> Python ->mutmut runmix.exs-> Elixir ->mix muzak
-
确认工具已安装。如果没有,请提供安装说明:
- Rust:
cargo install cargo-mutants - TypeScript:
npm install --save-dev @stryker-mutator/core - Python:
pip install mutmut - Elixir:在 deps 中添加
{:muzak, "~> 1.0", only: :test}
- Rust:
-
针对相关范围运行突变测试。尽可能优先限定到已更改的文件或包,而不是整个代码库:
# Rust (scoped to package) cargo mutants --package <package> --jobs 4 # TypeScript npx stryker run # Python (scoped to source) mutmut run --paths-to-mutate=src/ mutmut results # Elixir mix muzak
解析并报告结果
从突变测试工具的输出中提取:
- 生成的突变体总数
- 被杀死的突变体(测试检测到了更改)
- 存活的突变体(测试未检测到更改)
- 超时的突变体
- 突变分数百分比
分析存活的突变体
对于每个存活的突变体,报告以下三项:
- **位置:**文件和行号
- **突变:**更改内容(例如,“将
+替换为-”) - **含义:**这会放过哪类错误
常见突变类型及其存活所表明的问题:
- 算术(
+->-、*->/):计算未经过验证 - 比较(
>->>=、==->!=):边界条件未经测试 - 布尔(
&&->||、移除!):逻辑分支未覆盖 - 返回值(
true->false、Ok->Err):返回路径未经检查 - 删除语句(删除某行):副作用未断言
场景覆盖检查
在为存活的突变体推荐任何测试之前,先检查场景覆盖情况:
对于每个存活的突变体:
**步骤 1 — 场景检查:**是否有任何验收场景或领域场景(来自该切片的 acceptance_scenarios 或 domain_scenarios 数组,或计划中的 Confirmed Scenarios 部分)要求被突变的行为?
- 是 → 存在场景,但缺少相应测试。继续执行下文的“推荐缺失的测试”。
- 否 → 标记为待人工决策:
请勿继续为未覆盖的突变体推荐测试。没有场景就编写测试,只是在玩弄指标,并未测试实际行为。Surviving mutant at [file]:[line] has no GWT scenario requiring this behavior. Options: (a) Delete the code — this behavior may not be needed. (b) Add a missing acceptance or domain scenario — the spec is incomplete. The 100% kill rate still applies; this clarifies how to resolve it.
推荐缺失的测试
对于每个有覆盖场景的存活突变体,建议一个具体测试:
Surviving: src/money.rs:45 -- replaced `+` with `-` in Money::add()
Recommend: Test that adding Money(50) + Money(30) equals Money(80),
not Money(20). The current tests do not assert the sum value.
Surviving: src/account.rs:78 -- replaced `>` with `>=` in check_balance()
Recommend: Test the exact boundary -- check_balance with exactly zero
balance. Current tests only check positive and negative.
结构化输出
突变测试完成后,生成一个 MUTATION_RESULT 证据包:
{
"tool": "cargo-mutants",
"scope": ["src/money.rs", "src/account.rs"],
"total_mutants": 42,
"killed": 40,
"survived": 2,
"score": 95.2,
"survivors": [
{"file": "src/money.rs", "line": 45, "mutation_type": "arithmetic", "description": "replaced + with -"}
],
"verdict": "FAIL"
}
- **判定:**如果已更改文件的分数为 100%,则为
PASS;否则为FAIL - 在流水线模式下,保存到
.factory/audit-trail/slices/<slice-id>/mutation.json - 独立运行时,输出仅供参考——显示后继续执行质量门禁
强制执行质量门禁
要求的变异杀死率为 100%。必须杀死所有变异体。
- 如果得分为 100%:报告成功,继续创建 PR
- 如果得分低于 100%:列出所有存活变异体并给出建议。阻止 创建 PR,并明确发出警告。用户可以覆盖此限制,但默认 应先修复。
应做:
- 尽可能将变异测试范围限定为已更改的代码
- 报告存活变异体,并提供可执行的修复建议
- 修复后重新运行,以确认所有变异体均已被杀死
- 将超时视为已杀死(变异导致了故障)
不要:
- 在创建 PR 前跳过变异测试
- 在未报告的情况下接受存活变异体
- 仅更改了一个模块时,却对整个代码库运行变异测试
- 建议为应由领域类型负责的数据验证编写测试
流水线模式
由流水线编排器调用时:
FAIL判定会自动连同存活变异体列表一起路由回tdd技能。流水线负责处理返工路由——mutation-testing 只负责报告结果。MUTATION_RESULT数据包中的存活变异体详情必须具体到足以让 TDD 协作双方(文件、行号、变异类型、描述)编写有针对性的测试,而无需重新运行变异测试工具来了解失败原因。- 对于同一切片,流水线可能会多次调用 mutation-testing;每次运行都会覆盖该切片之前的
mutation.json。
强制执行说明
- 流水线模式:门禁。100% 杀死率是门槛——未达标将阻止合并。
- 独立模式:建议。Agent 会报告结果,但无法阻止用户覆盖限制。
硬性约束:
- 100% 杀死率:流水线模式下为
[H],独立模式下为[RP](阻止 PR,用户可附上有记录的理由后覆盖)
覆盖限制的文档要求请参阅模板目录中的 CONSTRAINT-RESOLUTION.md。
约束
- 100% 杀死率:100% 就是 100%。不是“差不多”,也不是“有理由的 98%”。低于 100% 的唯一途径是用户明确覆盖,此操作必须附上有记录的理由,解释每个存活变异体为何可以接受。“我想发布”不是理由。“这个变异体测试的是日志输出,而不是业务规则”才是理由。
- “没有场景就不写测试”:仅为杀死变异体而编写没有对应场景的测试是在钻指标的空子。该测试只能证明你能杀死变异体,不能证明这种行为很重要。如果没有场景涵盖该行为,正确做法是将这一缺口报告给团队——缺少的场景可能揭示了需求缺失。
验证
完成变异测试后,请验证:
- 已针对相关范围运行变异测试工具
- 已列出所有存活变异体的文件、行号和变异类型
- 在提出测试建议前,已逐一检查每个存活变异体是否有场景覆盖
- 对于有场景覆盖的每个存活变异体,都有具体的测试建议
- 对于没有场景覆盖的每个存活变异体,都已标记以供人工决策
- 变异得分为 100%(或用户已明确选择覆盖)
- 如果进行了修复,已重新运行变异测试以确认结果
如果有任何一项未满足,请在继续之前重新执行相关实践。
依赖项
此技能可独立使用,但最适合作为 PR 前的质量门禁。 它与以下内容集成:
- tdd:TDD 产出由变异测试验证的测试;存活变异体表明 TDD 周期遗漏了某种情况
- code-review:变异测试结果可为代码审查提供参考——审查者可以检查新增代码是否存在存活变异体
缺少依赖项?使用以下命令安装:
npx skills add jwilger/agent-skills --skill tdd