关于 tdd
面向开发者和编码 Agent 的 TDD 技能,强调通过公共接口验证行为,并以增量式红绿循环推进。它要求先确认测试边界和仓库使用的测试命令,再开始实现。
主要功能
- 01通过公共接口测试行为
- 02逐步进行红绿循环
- 03发现仓库专用测试命令
- 04确认测试边界与计划
- 05测试通过后再重构
适用场景
- 01围绕可观察行为规划测试
- 02逐项实现系统行为
- 03避免测试依赖内部实现
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ helderberto/ agent-skills --skill tdd安装后在 Claude Code 中输入/tdd确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/mocking.mdtests.mdui-tests.md详细介绍
测试驱动开发
理念
核心原则:测试应通过公共接口验证行为,而不是实现细节。代码可以彻底改变;测试不应改变。
好的测试采用集成测试的方式:通过公共 API 执行真实的代码路径。它们描述系统_做什么_,而不是_怎么做_。好的测试读起来就像一份规范——“用户可以使用有效购物车结账”能明确告诉你系统具备什么能力。这类测试经得起重构,因为它们不关心内部结构。
糟糕的测试与实现紧密耦合。它们会模拟内部协作者、测试私有方法,或通过外部手段验证(例如直接查询数据库,而不是使用接口)。警示信号是:重构时测试失败,但行为并未改变。如果重命名一个内部函数就导致测试失败,那么这些测试验证的是实现,而不是行为。
示例见 tests.md,模拟指南见 mocking.md,用户流程端到端测试见 ui-tests.md。
反模式:水平切片
不要先写完所有测试,再写完所有实现。 这就是“水平切片”——把 RED 阶段当作“写完所有测试”,把 GREEN 阶段当作“写完所有代码”。
这会产生糟糕的测试:
- 批量编写的测试验证的是_想象中的_行为,而非_实际的_行为
- 最终测试的是事物的_形态_(数据结构、函数签名),而非面向用户的行为
- 测试会对真正的变化不敏感——行为出问题时测试通过,行为正常时测试反而失败
- 你会超前于实际进度,在理解实现之前就敲定测试结构
正确做法:通过示踪弹进行垂直切片。一个测试 → 一个实现 → 重复。每个测试都基于上一轮的收获。由于你刚刚写完代码,因此清楚哪些行为至关重要,以及如何验证它们。
WRONG (horizontal):
RED: test1, test2, test3, test4, test5
GREEN: impl1, impl2, impl3, impl4, impl5
RIGHT (vertical):
RED→GREEN: test1→impl1
RED→GREEN: test2→impl2
RED→GREEN: test3→impl3
...
反模式:同义反复的测试
断言以与代码相同的方式重新计算预期值——expect(add(a, b)).toBe(a + b)、通过相同逻辑手动推导出的快照,或断言一个常量等于自身。这样的测试从构造上就会通过,永远无法与代码的结果产生分歧。
预期值必须来自独立的事实来源:可靠的字面值、完整算例或规范。示例见 tests.md。
工作流
0. 了解技术栈
TDD 循环具有普适性,命令则不然。在编写第一个测试前,先了解_当前_仓库如何运行测试,并在每个 RED 和 GREEN 阶段使用相应命令:
- 构建系统:
package.json、pyproject.toml、go.mod、Cargo.toml、Makefile - 优先使用仓库中已提交的包装器:
./gradlew、./mvnw、make test、仓库脚本——绝不要使用仓库未采用的全局安装工具 - 区分单个目标测试命令与完整测试套件命令——循环期间运行目标测试,完成前运行一次完整测试套件
- 查明测试所在位置、命名方式,以及相邻测试遵循的模式
- CI 工作流会显示实际用于门禁合并的命令
切勿假定使用 npm test。
1. 规划
探索代码库时,如果存在 GLOSSARY.md,请阅读它;否则阅读旧版 CONTEXT.md(在多上下文仓库中,GLOSSARY-MAP.md 会指明正确的文件),以确保测试名称和接口术语符合项目的领域语言,并遵守你正在处理区域的 ADR。
接缝是你进行测试的公共边界:在此处观察行为,而不深入内部。在编写任何测试之前,先写下要测试的接缝,每个接缝用一行说明该处的测试能捕获什么、无法捕获什么,并与用户确认:
询问:“公共接口是什么?我们应该测试哪些接缝?”
未经确认的接缝一律不编写测试。
编写任何代码之前:
- 与用户确认要测试的接缝
- 与用户确认要测试哪些行为(确定优先级)
- 识别深化模块的机会(小接口、深实现)——调用
codebase-design技能工具,了解相关术语和可测试性检查项 - 列出要测试的行为(而非实现步骤)
- 获得用户对计划的批准
你不可能测试所有内容。 提前就接缝达成一致,才能让测试投入聚焦于关键路径和复杂逻辑,而非每一种可能的边缘情况。
2. 示踪弹
编写一个测试,确认系统的一项功能:
RED: Write test for first behavior → test fails
GREEN: Write minimal code to pass → test passes
这是你的示踪弹——用于证明整个端到端路径正常工作。
3. 增量循环
对于每个剩余行为:
RED: Write next test → fails
GREEN: Minimal code to pass → passes
规则:
- 一次只编写一个测试
- 只编写足以通过当前测试的代码
- 不要预先考虑未来的测试
- 让测试聚焦于可观察的行为
4. 重构
只有在测试全绿后才能重构——测试为红时绝不重构。提取重复代码,深化模块(调用 codebase-design 技能工具,了解相关术语),并思考新代码揭示了现有代码的哪些问题。每一步之后都运行测试。