关于 tdd
面向工程 Agent 的测试驱动开发参考技能,规定以行为为中心的测试、事先确认的公共接口边界,以及逐步推进的红绿循环,并说明重构规则和常见测试反模式。
主要功能
- 01以行为为中心的测试指引
- 02测试前确认接口边界
- 03一次一个测试的红绿循环
- 04通过测试后再重构
- 05提供示例与模拟指南
适用场景
- 01围绕公共行为规划测试
- 02按垂直切片逐步实现功能
- 03避免脆弱或同义反复的测试
- 04测试通过后进行重构
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ opengovsg/ formsg-ai --skill tdd安装后在 Claude Code 中输入/tdd确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
frontend-verification.mdmocking.mdrefactoring.mdtests.mdagents/openai.yaml详细介绍
测试驱动开发
TDD 是红 → 绿循环。本技能是让这个循环产出值得保留的测试的参考:什么是好的测试、测试应放在哪里、反模式,以及循环规则。每个部分都适用于每个循环——在循环之前和过程中查阅,而不是事后再看。
探索代码库时,请阅读 CONTEXT.md(如果存在),让测试名称和接口用词符合项目领域语言,并遵守你正在修改区域的 ADR。
什么是好的测试
测试通过公共接口验证行为,而非实现细节。代码可以彻底改变,测试不应如此。好的测试读起来像一份规范——“用户可以使用有效购物车结账”能准确说明存在什么功能——而且能经受重构,因为它不关心内部结构。
示例请参阅 tests.md,模拟指南请参阅 mocking.md。
接缝——测试放在哪里
接缝是你进行测试的公共边界:无需深入内部即可观察行为的接口。测试应位于接缝处,而不是针对内部实现。
仅在事先约定的接缝处测试。 编写任何测试前,先写下要测试的接缝,并与用户确认。未经确认的接缝处不得编写测试。你无法测试所有内容——事先约定接缝,才能让测试工作聚焦于关键路径和复杂逻辑,而非每个边缘情况。
请问:“公共接口是什么,我们应该测试哪些接缝?”
当接口本身的形态尚未确定——模块应有多深、接缝应位于何处、接口应公开什么内容——请使用 /codebase-design 技能了解相关术语。它是模块、接口、深度、接缝、适配器、杠杆和局部性这些术语的共同参考来源;它仅供查阅,不是要运行的会话。
反模式
- 与实现耦合——模拟内部协作者、测试私有方法,或通过旁路验证(查询数据库,而不是使用接口)。判断标准:重构后测试失败,但行为并未改变。
- 同义反复——断言以代码相同的方式重新计算预期值(
expect(add(a, b)).toBe(a + b)、用相同方式手工推导的快照、断言某常量等于自身),因此测试必然通过,永远无法与代码结果不一致。预期值必须来自独立的真实依据——已知正确的字面值、完整示例或规范。 - 横向切分——先编写所有测试,再编写所有实现。批量测试验证的是_想象中的_行为:测试的是事物的_形态_,而不是面向用户的行为;测试会对真实变化失去敏感性,而且你会在理解实现前就确定测试结构。应改用纵向切片——一个测试 → 一个实现 → 重复;每个测试都是一枚示踪弹,会根据上一轮学到的内容作出调整。
工作流
1. 规划
探索代码库时,请使用项目的领域词汇表,让测试名称和接口用词符合项目语言,并遵守你正在修改区域的 ADR。通过循环提交时,请遵循项目的提交风格;记录实现中决策、供日后审查时,请遵循项目的面包屑约定——如果项目采用这些约定,两者都记录在项目的 Agent 文档中。
编写任何代码之前:
- 规划模块及其接口——深度、接缝位置和可测试性设计都由
/codebase-design技能提供 - 列出要测试的行为(而非实现步骤)
- 如果该切片会渲染 UI,请参阅 frontend-verification.md,了解视觉循环规则以及 agent-browser 与设计源之间的判定标准
2. 追踪弹
编写一个测试,确认系统的一件事:
RED: Write test for first behavior → test fails
GREEN: Write minimal code to pass → test passes
这是你的追踪弹,用于证明整条路径端到端可行。
对于视觉切片,RED 产物可以是故事或 dev-route 渲染结果,而非测试;GREEN 则通过视觉门槛来完成。纵向切片规则相同。请参阅 frontend-verification.md。
3. 增量循环
对于每个剩余行为:
RED: Write next test → fails
GREEN: Minimal code to pass → passes
规则:
- 一次只编写一个测试
- 只编写足以通过当前测试的代码
- 不要预先考虑未来的测试
- 让测试聚焦于可观察的行为
4. 重构
所有测试通过后,查看重构候选项:
- 提取重复代码
- 深化模块(将复杂性移至简单接口之后)
- 在适当的地方应用 SOLID 原则
- 思考新代码揭示了现有代码的哪些问题
- 每完成一个重构步骤后运行测试
**切勿在 RED 状态下重构。**先达到 GREEN。
每轮检查清单
[ ] Test describes behavior, not implementation
[ ] Test uses public interface only
[ ] Test would survive internal refactor
[ ] Code is minimal for this test
[ ] No speculative features added
[ ] Commit follows the project's commit style (one logical change per commit)
[ ] Any non-obvious in-impl decision is captured as a breadcrumb
面包屑记录
对于实现过程中不明显的选择,按照项目的面包屑约定,在 .scratch/<feature>/decisions.md 中追加一条记录。跳过机械或显而易见的选择——噪声会让评审者停止阅读。重大的架构决策应记录在 ADR 中,而不是面包屑记录中。
循环结束后,下一步是 /prepare-for-review。