| name | tdd |
| description | 测试驱动开发。当用户想要以测试为先的方式构建功能或修复 bug、提到"红-绿-重构"或需要集成测试时使用。 |
测试驱动开发
TDD 是红 → 绿循环。本技能是让该循环产生值得保留的测试的参考:什么是好测试、测试应该放在哪里、反模式是什么,以及循环的规则。每个章节在每个循环中都适用——在循环之前和期间参考它们,而不是之后。
在探索代码库时,阅读 CONTEXT.md(如果存在),使测试名称和接口词汇表与项目的领域语言一致,并尊重你正在接触的区域的 ADR。
什么是好测试
测试通过公共接口验证行为,而不是实现细节。代码可以完全改变;测试不应随之改变。好的测试读起来像一份规格说明——"用户可以使用有效购物车结账"准确告诉你存在什么能力——而且因为它不关心内部结构,能在重构中存活。
参见 tests.md 获取示例,mocking.md 获取 mocking 指南。
接缝(Seams)——测试的位置
接缝是你测试时的公共边界:你观察到行为而不深入内部的接口。测试放在接缝处,绝不要针对内部。
只在预先约定的接缝处测试。 在编写任何测试之前,写下要测试的接缝并与用户确认。没有测试会在未经确认的接缝处编写。你不可能测试所有东西——事先约定接缝的做法,是让测试工作落在关键路径和复杂逻辑上,而不是每个边界情况上。
询问:"公共接口是什么,我们应该测试哪些接缝?"
反模式
- 与实现耦合——mock 内部协作对象、测试私有方法、或通过侧信道验证(直接查询数据库而不是使用接口)。识别信号:重构时代码行为没有改变,但测试失败了。
- 循环论证(Tautological)——断言以与代码相同的方式重新计算期望值(
expect(add(a, b)).toBe(a + b)、以同样方式手工推导的快照、断言常量等于自身),因此它构造性通过,永远不可能与代码不一致。期望值必须来自独立的真实来源——已知正确的字面量、手工验证的示例、规格说明。
- 水平切片——先写所有测试,再写所有实现。批量测试验证的是想象中的行为:你测试了事物的形状而非面向用户的行为,测试对真实变更变得不敏感,并且在理解实现之前就承诺了测试结构。改用垂直切片——一个测试 → 一个实现 → 重复,每个测试都是一颗示踪子弹,响应上一循环教会你的内容。
循环规则
- 红在绿之前。 先编写会失败的测试,然后只写足以通过它的代码。不要预见未来的测试或添加臆测的功能。
- 一次一个切片。 每个循环一个接缝、一个测试、一个最小实现。
- 重构不是循环的一部分。 它属于审查阶段(参见
code-review 技能),而不是红 → 绿实现循环。