AI 编码时代的 TDD
在 AI coding 场景下,把 TDD 视为可执行规格、任务边界和自动验收器的工作方式。
#type / synthesis
#status / growing
#tech / dev / test
#tech / ai
[!info] related notes
- 所属 MOC: 测试驱动开发 MOC, AI MOC
- 相关概念: 测试驱动开发(TDD), 自测试代码(Self-Testing Code), OpenAI Codex, AI 辅助前端开发工作流, AI Code Review 与 AI 重构
- 易混淆概念: 前端测试, 后端测试
AI 编码时代的 TDD
范围
这篇笔记关心的不是传统 TDD 定义本身,而是一个新问题:
为什么在 AI coding 时代,TDD 反而更重要,而不是更过时。
为什么要把这些内容放在一起理解
AI 最容易出现三类问题:
- 写出“像对的代码”,但不一定真的对
- 一次跳太多步,把多个需求混在一起实现
- 在大上下文里不断追加生成,局部设计越来越脏
TDD 正好对冲这三类风险,因为它会把任务收束到:
- 一个明确行为
- 一个可执行测试
- 一个最小实现
- 一个可验证的重构步骤
一个核心判断
在 AI 时代,TDD 不只是开发习惯,更像 agent 的:
- 可执行规格
- 局部任务边界
- 自动验收器
- 重构安全网
这也是为什么“先让 AI 写一大坨代码,再顺手补测试”通常不稳。那是 test-after,不是 TDD。
AI-TDD 更稳的工作流
1. 先由人写测试清单
这一层本质上是在切需求、定边界、排优先级,最好不要完全外包给模型。
2. 让 AI 只写一个 failing test
要求它:
- 只覆盖当前一个行为
- 不要实现代码
- 不要一次写多个场景
3. 人确认测试是否真的代表需求
因为 AI 很容易写出“形式正确但业务不准”的测试。
4. 让 AI 只写最小实现
明确限制:
- 只为当前测试变绿
- 不提前实现未覆盖逻辑
- 不改测试去迎合错误实现
5. 先跑最小测试,再扩大验证范围
这样反馈快、定位准,也能避免每一轮都把成本拉到全量测试。
6. 再让 AI 做 Refactor
AI 连续生成时最容易把代码局部做脏,因此重构最好被显式当成单独一步,而不是默认省略。
7. 最后用独立 reviewer 或 verifier 检查
最好不要让“写的人”和“验的人”完全是同一个 prompt 视角。
Prompt 怎么写更稳
先写 failing test
先不要实现功能。
基于下面需求,只写 1 个新的 pytest 单测。
要求:
1. 只覆盖“VIP 打 9 折”这一个行为
2. 测试名要能直接表达业务意图
3. 不要生成实现代码
4. 不要一次写多个场景
5. 解释这个测试为什么应该先写
再写最小实现
现在只修改实现文件,让刚才新增的测试通过。
要求:
1. 只做最小改动
2. 不要提前实现未被测试覆盖的逻辑
3. 不要改测试
4. 返回前说明还有哪些需求尚未覆盖
最后做重构
在保持现有测试全部通过的前提下重构实现。
目标:
1. 消除重复
2. 改善命名
3. 不改变外部行为
4. 不新增无测试覆盖的分支
规则文件里最值得固化什么
如果项目里已经使用 AGENTS.md、Cursor Rules 或类似规则文件,最值得固化的是:
- 功能改动先新增或更新测试
- 修 bug 先写复现测试
- 禁止通过删断言来“修”测试
- 先跑受影响的最小测试集,再跑更大范围
- 重构不得改变外部行为
这样做的意义,是把 TDD 从“个人习惯”升级成“仓库级执行约束”。
最短记忆方式
传统时代,TDD 帮人写出更稳的代码;AI 时代,TDD 还负责让模型别乱写。
参考资料
- https://martinfowler.com/articles/exploring-gen-ai/06-tdd-with-coding-assistance.html
- https://developers.openai.com/codex/prompting
- https://developers.openai.com/codex/guides/agents-md
- https://docs.github.com/en/copilot/tutorials/copilot-chat-cookbook/testing-code
- https://cursor.com/docs/subagents.md