| name | tdd |
| description | Red-Green-Refactor 测试驱动开发纪律。 Use when: 写新功能代码、修 bug、任何实现工作。 Not for: 纯文档、纯调研、已有充分测试的 trivial 改动。 Output: 失败测试 → 最小实现 → 重构,全程有测试保护。
|
| triggers | ["写代码","test first","TDD","红绿重构"] |
TDD(测试驱动开发)
先写测试。看它失败。写最少代码通过。
铁律:没有失败的测试,就没有实现代码。
核心知识
为什么顺序绝对不能反?(4 个常见异议的反驳)
| 异议 | 真相 |
|---|
| "写完再补测试,也能验证" | 测试写在实现后会立即通过——你永远不知道它是否真的在测你要的东西 |
| "我手工测了所有 case" | 手工测试没有记录、不能重跑、下次改动时你会忘了测什么 |
| "删掉 X 小时的工作太浪费" | 沉没成本谬误。留着无法信任的代码才是浪费 |
| "TDD 是教条,务实应该灵活" | TDD 本身就是务实的——它比事后调试快,能防止回归,是真正的捷径 |
Tests-after 回答"这段代码做了什么";tests-first 回答"这段代码应该做什么"。两者不等价。
Red-Green-Refactor 循环
RED → 写一个会失败的测试
↓ 必须亲眼看到它失败(失败原因要对,不是 typo)
GREEN → 写最少代码让测试通过
↓ 必须亲眼看到它通过(其他测试也要绿)
REFACTOR → 消除重复、改善命名
↓ 保持绿灯,不添加行为
重复 →
关键决策点:
- RED 阶段测试立即通过?→ 你在测已有行为,修测试
- RED 阶段报错而非失败?→ 修错误直到"正确地失败"
- GREEN 阶段其他测试挂了?→ 立即修,不要继续
- REFACTOR 后测试变红?→ 撤销 refactor,重来
Bug Fix 模式
Bug 修复和新功能一样,必须先写失败测试。入口动作:先填诊断胶囊。
诊断胶囊模板 → refs/bug-diagnosis-capsule.md
永远不要在没有测试的情况下修 bug。
流程
任务开始
↓
写一个描述期望行为的测试
↓
跑测试 → 失败?→ 继续
→ 通过?→ 你在测已有行为,修测试
↓
写最少实现代码
↓
跑测试 → 通过?→ 继续
→ 失败?→ 修代码(不改测试)
↓
全量测试通过?→ Refactor → 重复
Quick Reference
好测试的标准
- 一个行为:名字里有"and"?拆分
- 名字描述行为:
rejects empty email 好于 test1
- 测真实代码:避免只测 mock
口令:立即停止的 Red Flags
听到自己说以下任何一句 → 删掉代码,从测试重新开始:
- "应该能过"、"大概没问题"、"先快速实现一下"
- "测试我写完功能再补"、"这个太简单了不用测"
- "我已经手工验证过了"、"精神一致就够了,不用走形式"
- "这个情况不一样,因为……"、"留着参考,写测试时再删"
所有这些都是理由化(Rationalization)。没有例外。
Common Mistakes
| 错误 | 正确做法 |
|---|
| 先写实现,再补测试 | 删掉实现,从失败测试开始 |
| 跳过"看它失败"步骤 | 必须跑测试亲眼看失败 |
| 测试立即通过就继续 | 停下来——测试没有测到真正的行为 |
| 修 bug 时直接改代码 | 先写复现 bug 的失败测试 |
| GREEN 阶段过度实现 | 只写能通过当前测试的最少代码 |
| mock 了所有东西 | 代码耦合度太高,用依赖注入简化 |
和其他 skill 的区别
- vs
debugging:TDD 是预防性的(写代码前);debugging 是修复性的(bug 出现后)。两者的交叉点:debugging 发现 bug 后,Phase 4 必须先写失败测试再修(此时切换回 TDD 模式)
- vs
quality-gate:TDD 是开发过程中的纪律;quality-gate 是提交前的验收检查
下一步
完成功能实现后 → 直接加载 quality-gate 做提交前验收。不要停下来问operator(§17)。