TDD教练Skill tdd-coach

指导测试驱动开发,遵循红-绿-重构循环来编写聚焦行为的测试和最小化实现。适用于以TDD方式开发功能或修复Bug的场景,强调通过公开接口验证行为而非实现细节。关键词:TDD,测试驱动开发,红绿重构,集成测试,测试先行

测试 0 次安装 2 次浏览 更新于 7/8/2026

name: tdd-coach description: “指导测试驱动开发,遵循红-绿-重构循环来编写聚焦行为的测试和最小化实现。当用户希望以TDD方式开发功能或修复Bug、提到"红绿重构"、需要进行集成测试、或要求测试先行开发时使用。”

测试驱动开发

核心理念

基本原则:测试应该通过公开接口验证行为,而不是验证实现细节。代码可以完全重写,但测试不应因此而变。

好的测试是集成风格的:它们通过公开 API 执行真实的代码路径。好的测试描述的是系统"做什么",而不是"怎么做"。一个好的测试读起来就像一份规格说明——"用户可以用有效购物车结账"清楚地说明了系统具备什么能力。这样的测试能在重构中存活下来,因为它们不关心内部结构。

坏的测试与实现耦合。它们 mock 内部协作者、测试私有方法、或通过外部手段(比如直接查询数据库而不是使用接口)来验证。一个危险信号是:你重构了代码,测试却挂了,但行为并没有变。如果你重命名了一个内部函数导致测试失败,说明那些测试测的是实现,不是行为。

参见 tests.md 了解示例,以及 mocking.md 了解 mock 使用指南。

反模式:水平切片

不要先写完所有测试,再写所有实现。 这就是"水平切片"——把红色阶段当成"写所有测试",绿色阶段当成"写所有代码"。

这样会写出糟糕的测试

  • 批量写的测试测的是_想象中的_行为,而不是_实际的_行为
  • 你最终测的是_数据结构的形状_(数据结构、函数签名),而不是面向用户的行为
  • 测试对真正的变化不敏感——行为坏了测试却通过,行为没问题测试却失败
  • 你跑在了前灯之前,在理解实现之前就绑定了测试结构

正确做法:通过"示踪弹"做垂直切片。写一个测试 → 写一个实现 → 循环。每个测试都基于上一轮循环中学到的东西。因为你刚写完代码,你清楚地知道哪些行为重要、如何验证。

错误(水平切片):
  红:   test1, test2, test3, test4, test5
  绿:   impl1, impl2, impl3, impl4, impl5

正确(垂直切片):
  红→绿:test1→impl1
  红→绿:test2→impl2
  红→绿:test3→impl3
  ...

工作流程

1. 规划

在写任何代码之前:

  • [ ] 与用户确认需要哪些接口变更
  • [ ] 与用户确认要测试哪些行为(确定优先级)
  • [ ] 识别适合做深模块的机会(小接口,深实现)
  • [ ] 为可测试性设计接口
  • [ ] 列出需要测试的行为(不是实现步骤)
  • [ ] 获得用户对计划的确认

要问:"公开接口应该是什么样的?哪些行为最重要、需要测试?"

你不可能测试所有东西。 与用户确认哪些行为最关键。把测试精力集中在关键路径和复杂逻辑上,而不是每个可能的边界情况。

2. 示踪弹

写一个测试,验证系统的一个行为:

红:   写第一个行为的测试 → 测试失败
绿:   写最少的代码让测试通过 → 测试通过

这就是你的示踪弹——证明这条路径端到端是通的。

3. 增量循环

对每个剩余的行为:

红:   写下一个测试 → 失败
绿:   写最少代码让它通过 → 通过

规则:

  • 一次只写一个测试
  • 只写刚好让当前测试通过的代码
  • 不要预判未来的测试
  • 保持测试聚焦在可观察的行为上

4. 重构

所有测试通过后,寻找重构候选

  • [ ] 提取重复代码
  • [ ] 加深模块(把复杂性藏在简单接口后面)
  • [ ] 在自然的地方应用 SOLID 原则
  • [ ] 思考新代码揭示了已有代码的什么问题
  • [ ] 每次重构后运行测试

绝不在红色阶段重构。 先到绿色阶段。

每轮循环检查清单

[ ] 测试描述的是行为,不是实现
[ ] 测试只使用公开接口
[ ] 测试能在内部重构中存活
[ ] 代码是针对当前测试的最小实现
[ ] 没有添加推测性的功能