| 名称 | Python-Unit-Test |
| 描述 | 一站式「审计 → 测试 → 修复」闭环技能(ATF)。对目标代码文件执行代码审计,基于审计产物生成单元测试,运行测试并对失败用例聚类修复,最终输出总结报告。Use when user asks to 审计并测试、一条龙测试、分析文件并写测试并反馈、test all in one、ATF、测试闭环。 |
Python-Unit-Test (ATF)
对单个/多个目标文件执行「代码审计 → 测试生成 → 执行修复 → 结果反馈」的阶段化闭环。 阶段间通过标准产物文件耦合(硬契约),不依赖对话上下文传递。
本技能自包含各阶段完整能力,可直接独立办事,不依赖任何外部基础技能:
- 审计 →
references/audit-guidelines.md- 契约来源仲裁 →
references/contract-sources.md(贯穿 A/T/F 的共同铁律)- 测试生成 →
references/test-patterns.md- 修复 →
references/fix-guidelines.md- 变异自检 →
scripts/mutation_check.py各阶段按产物文件硬耦合编排,全部逻辑与指导内置于本技能目录内。
🔴 第一铁律:测试的目的是暴露错误代码,不是变绿
断言的预期只来自被测实现之外的证据(调用方语义 / 外部 API / 同类实现 / 规范性文档 / 命名常量)。 凡从实现表达式反推预期的测试,实现错了它也跟着对 —— 永远绿,永远没用。 因此:
- 不追求通过率 100%:红色是产出,不是噪声。
- 不追求覆盖率:覆盖率只说明“没测到”,不说明“测到了”。
- 必须做阶段 M 变异自检:它是唯一能证明“测试保红”的指标。
- 详见
references/contract-sources.md。
When to Use
- 用户要求“分析这个文件并写测试”、“审计+测试+修复一条龙”
- 需要同时产出:审计报告 + 测试代码 + 执行结果 + 缺陷单 + 总结报告
- 触发词:
Test-all-in-one、ATF、审计测试修复、一条龙测试、测试闭环
输入参数
| 参数 | 必填 | 说明 | 默认 |
|---|---|---|---|
target |
✅ | 目标文件或目录路径 | — |
max_fix_rounds |
❌ | 最大修复轮数 | 3 |
覆盖率不设门槛:
--cov仅作参考诊断,不是通过/失败条件。思考重心是深度逻辑实现 (行为契约),不是行覆盖数字。行为覆盖 > 行覆盖。
模式固定为 full(完整闭环),不支持单阶段模式。
核心方法论:模块画像驱动
阶段 T 的策略由阶段 A 产出的模块画像(module_type + properties + strategy_notes)决定,
而非死守一条通用规则:
- 广度(测什么) ←
module_type(八类模块类型,保证测试点基线不遗漏) - 深度(聚焦什么) ←
properties(正交性质标签,叠加深层预期用例) - 决策(怎么做) ←
strategy_notes(软决策:场景 → 推荐策略,允许按实际变通)
详见 references/audit-guidelines.md「模块画像」一节与 references/test-patterns.md「按模块画像聚焦」一节。
工作流(full 固定)
阶段 A 审计 → 阶段 T 测试 → 阶段 F 修复 → 阶段 M 变异自检 → 总结
│ │ │ │ │
A1 audit_report.md T1 test_<file>.py F1 修复/bug单 M1 mutation_report final_report.md
A2 analysis.json T2 执行结果 F2 回归结果 M2 变异检出率
阶段 M 是验收关卡:它回答“如果我在这段代码里改一刀,测试会红吗”。 跳过 M 就直接总结,等于交付一套不知道有没有检测力的套件。
阶段 A:代码审计 (Audit)
- 读取
target:目标文件本身 + 其直接引用的关联代码(import 的模块、被调用的函数/类定义等,用于理解上下文与契约);契约溯源需要时读调用方;不追求读全仓库,也不因“禁读无关文件”牺牲契约理解 - 按
references/audit-guidelines.md六维度分析(架构/质量/安全/性能/测试/可维护性/契约溯源 + 契约一致性) - 模块画像(必做):判定
module_type(八类)+properties(正交标签)+strategy_notes(软决策),落到analysis.json - 疑点必登记:审计中任何矛盾/不确定问题必须落盘到
analysis.json的unresolved_questions或risk_findings,禁止静默丢弃 - 产出并落盘:
test_output/01_audit_report.md(人读,含复现代码)test_output/analysis.json(机读:模块画像、函数清单、behavioral_contracts 行为契约、contract/contract_conflicts、风险点、建议测试点分级、unresolved_questions)
- 若发现高风险缺陷:先行输出规范 bug 单(含复现代码)到
test_output/bug_reports/
退出条件:A2 落盘完成(含 module_type + properties + behavioral_contracts)。禁止跳过 A 直接进入 T。
阶段 T:测试生成与执行 (Test)
- 输入硬契约:读取
analysis.json(模块画像 + 函数清单 + behavioral_contracts + contract + unresolved_questions) - 按模块画像聚焦(
references/test-patterns.md§0):- 广度:按
module_type基线逐项覆盖 - 深度:按
properties各标签叠加深层预期用例(is_async →_run;has_module_state → autouse fixture;has_side_effects → 假对象只挡边界;has_time_semantics → 时序契约用例;has_data_integrity → 不截断/不丢弃反向用例;strong_typed → 倾向真实依赖) - 依赖探测:
real_env_deps可用真实依赖推荐直接 import;仅依赖少量方法的普通依赖可权衡用假对象
- 广度:按
- 按
references/test-patterns.md+templates/test_file.py.j2生成tests/test_<file>.py(AAA、parametrize、按 P0/P1/P2 分级,P0 行为契约优先) - 契约一致性用例必测:
behavioral_contracts(P0 优先)与contract_conflicts/unresolved_questions每项至少 1 条用例;反向用例预期来自行为契约而非代码行为 - 运行 pytest 并落盘
test_output/02_test_report.txt;--cov仅作参考诊断(可选,不设门槛) - 记录四类计数(缺一不可):
passed / failed / xfailed / unspecified
⚠️ 禁止只报 passed 数。
xfailed= 已知未修缺陷数,unspecified= 无 oracle 用例数, 二者必须与 passed 并列呈现。只报 “N passed” 会把“带病交付”伪装成“全绿交付”。
退出条件:
- P0 契约用例(且
oracle != "none")全部通过、P1/P2 无未决失败 → 可跳过 F,直接进 M - 有失败 → 进入 F
- 契约冲突用例保持
failed或xfail(strict=True)均属正常,不视为未达标
- 输入硬契约:读取
02_test_report.txt的失败明细 - 运行
scripts/cluster_errors.py聚类失败(按错误类型/函数/相似度分组) - 🚦 归因比例自检(硬闸门):若归因“测试 bug”的失败 > 50% → 停止修测试,回阶段 A 重审契约来源
- 按三问定案逐组处理(详见
fix-guidelines.md §2+contract-sources.md):- Q1 无 E1–E5 外部证据 →
UNSPECIFIED:写对偶用例,禁止单方面改为实现侧取值 - Q2 有证据且与实现冲突 → 被测代码缺陷:出 bug 单,测试保持红,改源码须先征得用户确认
- Q2’ 有证据且与实现一致,失败源于桩/隔离/输入构造 → 修正用例,并登记
expectation_revisions(含confidence) - 设计缺陷/无法修复 → 输出 bug 单并标注 BLOCKED
- Q1 无 E1–E5 外部证据 →
- 回归重跑(最多
max_fix_rounds轮)
退出条件:无未决 P1、无未决 UNSPECIFIED 冲突、所有已确认缺陷均已落单 (或达到最大轮数 / 用户喊停)。
❗ 通过率 100% 不再是退出条件。 以全绿为目标修完的套件, 几乎必然是把缺陷固化成了预期。红色是审计的产出,不是需要清除的噪声。
阶段 M:变异自检 (Mutation Spot-check) —— 验收关卡
目的:量化「测试到底保不保红」。这是唯一不依赖任何基准文件(.bak / 原始仓库 / 既有测试)的检测力度量。
- 基于
analysis.json的风险点与 P0 契约,编写 8–12 个变异点(JSON 列表): 常量翻转、比较方向反转、索引首尾互换、分支条件取反、快照提前/延后、 兜底值增删、回退链截断、集合范围起点偏移;并必须覆盖规则 6 的四类「值外变异」 (执行上下文、字段一致性、严格边界、守卫/取值来源,见references/test-patterns.md)。 - 运行
scripts/mutation_check.py(自动:注入 → 跑测试 → 还原 → 记录):python scripts/mutation_check.py --target <file> --tests <test_file> \ --mutations <mutations.json> --out test_output - 产出
test_output/mutation_report.md+mutation_report.json(检出率 + 未检出点清单)。 - 未检出点 → 回阶段 A 补契约;若确无 oracle,在报告标注「该风险点当前测试无保护」。
退出条件:变异检出率已记录并写入报告。检出率低不阻断流程,但必须在首屏暴露。
总结阶段
运行 scripts/summary_gen.py 生成 test_output/03_final_report.md。
报告首屏四项主指标(取代“通过率 + 覆盖率”):
| 指标 | 含义 |
|---|---|
| 已确认缺陷数 | 有 E1–E5 证据、落入 bug_reports/ 的条数(建议类不计入) |
| 变异检出率 | 阶段 M 结果 —— 测试是否真的保红 |
| 无 oracle 用例占比 | unspecified / 总数 —— 有多少结论其实没有依据 |
| 已知未修冲突数 | xfailed + failed 中已确认的契约冲突 |
覆盖率移入附录:它只说明“没测到”,不说明“测到了”,不作为质量证据。
产物契约(硬耦合)
| 产物 | 路径 | 生产者 | 消费者 |
|---|---|---|---|
| A2 机读分析 | test_output/analysis.json |
A / F | T / M |
| T2 失败明细 | test_output/02_test_report.txt |
T | F |
| 缺陷单 | test_output/bug_reports/*.md |
A/F | 总结 |
| M2 变异报告 | test_output/mutation_report.md / .json |
M | 总结 |
| 总结报告 | test_output/03_final_report.md |
总结 | 用户 |
规则:产物必须文件落盘;阶段切换只认产物,不认对话记忆。
运行命令速查
# 单文件测试
python -m pytest tests/test_<file>.py -v
# 覆盖率(仅参考诊断,不设门槛)
python -m pytest --cov=<module> --cov-report=term-missing
# 失败聚类
python scripts/cluster_errors.py test_output/02_test_report.txt
# 变异自检(阶段 M:验证测试是否保红)
python scripts/mutation_check.py --target <file> --tests <test_file> \
--mutations <mutations.json> --out test_output
# 汇总报告
python scripts/summary_gen.py test_output/
常见失效模式(自检清单)
跑完问自己这四个问题,任一为“是”说明本轮产出的测试不保红:
- 失败是不是几乎全被归因成“测试写错了”? 是 → 契约基线就是被测实现,回阶段 A。
- 有没有断言的预期是从实现表达式抄来的? 有 → 该断言永远绿,重写。
- 报告首屏是不是只写了 “N passed”? 是 → 在掩盖 xfailed / unspecified。
- 有没有跑变异自检? 没跑 → 你不知道这套测试有没有检测力。
边界与安全
- 本技能不新增工具,内部按阶段执行审计/测试/修复动作
- 改被测源码前必须先确认(外部副作用原则)
- 只读取
target及其直接引用的关联代码(契约溯源需要时可读调用方),不扩散到无关代码文件