Test-Driven Development
TDD 是红 → 绿循环。这个 skill 使循环产生值得保留的测试:好测试的标准、放哪、反模式、循环规则。每个章节在每轮循环中都要参考——在循环前和循环中查阅,不要等事后。
探索代码库时,读取 CONTEXT.md(如存在),使测试名和接口词汇匹配项目的领域语言,并尊重正在触及区域的 ADR。
好测试的标准
测试通过公共接口验证行为,不是实现细节。代码可以完全改变,测试不应受影响。好测试读起来像规格说明——"用户能用有效购物车结账"——告诉你确切功能。测试能在重构中存活,因为它们不关心内部结构。
测试指南
- 通过 seam 测试:seam 是测试的公共边界,是观察行为且不触及内部的接口
- 只在预先确定的 seam 上测试:写测试前,定好 seams 并跟用户确认。没有测试写在未经确认的 seam 上
- 问:"公共接口是什么?应该在哪些 seams 上测试?"
Mock 指南
- 只 mock 真正的外部依赖(第三方服务、数据库、网络)
- 不要 mock 同一模块内的东西
- In-memory adapter 比 mock 好——它测试真实行为,不是 mock 行为
- 测试数据工厂比硬编码 fixture 好——它们表达测试意图而不隐藏细节
反模式
- Implementation-coupled — mock 内部协作者、测试私有方法、通过侧面渠道验证。标志:重构时测试失败但行为没变
- Tautological — 断言重新计算期望值(
expect(add(a, b)).toBe(a + b)),总是通过永远检测不到问题。期望值必须来自独立来源 - Horizontal slicing — 先写所有测试再写所有实现。批量测试验证的是"想象的行为"。按垂直切片——一个测试 → 一个实现 → 重复
循环规则
- 先红后绿。先写失败的测试,然后只写刚好够让它通过的代码。不要预判未来测试
- 一次一个切片。一轮循环一个 seam、一个测试、一个最小实现
- 重构不属于循环。重构属于审查阶段,不在红 → 绿实现循环中