为什么 AI 编程 TDD 比人写代码时更重要
一句话结论:AI 编程 TDD 的核心价值在于”测试先行”——先写失败测试再让智能体实现,测试就成了智能体无法伪造的契约,它能同时拦住幻觉 API 、丢边界条件和头痛医头这三类典型问题。
智能体写代码的速度快到难以监督:几百行代码几秒生成,每一行都”看起来对”。而看起来对,恰恰是最危险的。没有契约约束时,智能体的典型产出模式是:先写实现,再补测试——这种测试只是确认代码现状,验证的是”代码做了什么”而不是”它应该做什么”,天然通过,毫无约束力。
Red-Green-Refactor 在智能体时代的分工
循环本身没变,变的是谁握哪一端:你拥有规格,智能体拥有实现。
- RED(你):写一个描述目标行为的失败测试并运行,确认它因预期的原因失败。这个失败输出就是规格。
- GREEN(智能体):把测试文件交给智能体,指令只给最小约束:”实现 Cart 类让 test_cart.py 通过,不许修改测试文件,跑完测试并贴出输出”。
- REFACTOR(双方):绿灯之后,让智能体重构实现以提升可读性,每步重构后重跑测试。你负责审查和批准。
关键纪律只有一条:永远不要让智能体把”自己写的测试”当作主要验证手段。它的测试会编码它自己的假设——包括错的那部分。
把纪律固化到工具里,而不是靠自觉
CLAUDE.md 里写”遵循 TDD”只是建议,模型可以选择不听。要确定性执行,用钩子:
// .claude/settings.json — 每次编辑文件后自动跑测试
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"command": "pytest tests/ -x --tb=short 2>&1 | tail -20"
}
]
}
}
-x 遇到首个失败即停,tail -20 防止几百行测试输出淹没上下文。同时在 CLAUDE.md 里写明红线:不许修改或删除已有测试来让测试通过;测试失败修实现,不修测试。意图靠 CLAUDE.md,执行靠钩子,两者缺一不可。
三个进阶手段
- 属性测试:对逻辑密集的代码,用随机输入验证不变量(比如购物车总价恒等于各项之和),智能体无法通过硬编码糊弄。
- 黄金测试:重构遗留代码前,先把当前行为固化成快照测试,智能体改动后行为是否漂移一目了然。
- 变异测试:用 mutmut 之类工具故意向实现注入缺陷,看测试能不能抓住。变异得分低,说明智能体写的测试是”怎么跑都过”的装饰品。
什么时候不值得用
一次性脚本、探索性原型、还没想清楚契约的实验代码,TDD 的循环开销大于收益,直接 vibe coding 更合适。反过来,涉及鉴权、资金、个人信息的代码,以及你无法靠肉眼判断对错的领域,测试先行不是选项而是底线。
TDD 解决”写对了没有”,但写对了不等于安全——上线前还应过一遍 AI 生成代码安全审查清单;跑不通时的定位流程见 AI 生成代码调试四步法。如果团队已经在做计划先行的工作流,TDD 可以无缝接入 Plan/Act 分离工作流 的 Act 阶段;另外 AI 生成单元测试 里讨论的”覆盖率上去了还是抓不到 bug”,本质就是缺了测试先行这个环节。
让 AI 自己写测试再自己写实现,不行吗?
TDD 循环会不会太慢?
测试失败时智能体去改测试文件怎么办?
参考来源:Claude Code 官方文档 Best Practices(测试先行与 Hooks 章节)、 qaskills.sh 与 matterai.so 关于 TDD with AI Agents 的实践总结。










评论 (0)