关于 tdd
面向代码库开发的编码技能,指导 Agent 通过小步红—绿—重构循环实现变更,并提供测试选择、验证和报告阻碍的规则。
主要功能
- 01小步红—绿—重构循环
- 02判断是否需要测试的标准
- 03测试接口与协作者选择指南
- 04保持测试预期真实的规则
- 05验证与完成情况报告
适用场景
- 01为新增行为编写回归测试
- 02修复前复现已报告的缺陷
- 03测试优先难以实行时检查变更
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ marcellocurto/ skills --skill tdd安装后在 Claude Code 中输入/tdd确认已加载。
附带文件agents/openai.yamltest-evidence.md
详细介绍
测试驱动开发
以小步红 → 绿 → 重构循环开展工作:先将一个行为写成测试,观察测试失败,再实现该行为,最后整理修改过的代码。如果项目中有术语表和相关 ADR(无论文件名是什么),请先阅读,确保测试使用项目中的领域术语。
判断是否需要编写测试
只有当改动新增或改变了用户或调用方今后会依赖的规则时,才编写测试。测试旨在捕捉此类规则可能出现的实际回归;仅仅为了提高覆盖率并不足以成为编写测试的理由。如果改动没有引入这类规则,请用一行说明,并直接实现,无需执行测试循环。
测试描述系统的行为。不要编写断言某个功能、路由、选项或默认值不存在的测试。承诺的拒绝行为或默认行为都属于行为,因此应测试实际结果:例如,端点在没有凭据时返回 401,或者破坏性标志默认关闭。移除行为时,删除覆盖该行为的测试,找出仍在使用的调用方,并运行剩余的测试套件;它只覆盖已测试过的内容,因此还应直接检查剩余调用方。
起草设计、UI 或想法时不要编写测试。等行为达成一致并开始构建时再编写测试。
选择测试
编写测试前,明确说明规定预期结果的要求、起始条件,以及测试应捕捉的实际故障。
- 通过负责该行为的接口进行测试。这可以是公共 API,也可以是内部模块接口。优先使用现有接口和代码附近的测试惯例。
- 如果测试所声称的行为涉及协作者的行为,就使用真实协作者。只有在需要控制时间、随机性或故障,或者依赖不属于测试的验证范围时,才替换依赖。test-evidence.md 列出了常见契约中哪些内容可作为证据,以及何时适合使用测试替身。
- 覆盖关键路径和复杂逻辑。不要覆盖每个边界情况。
- 不要暴露私有状态,也不要仅为方便编写测试而添加公共方法、包装器或配置。如果需要讨论接口本身,请使用
codebase-design技能。
循环
功能和错误修复遵循相同的循环。对于错误,首个测试应通过负责该故障行为的最窄接口复现报告中的问题,并遵循代码附近的测试惯例。
- 选择最小的可观察行为。
- 为其编写一个有针对性的测试。
- 在更改生产代码之前运行测试,并确认测试因缺少该行为而失败。如果失败是由设置问题或测试错误导致的,先修复测试。如果测试通过,检查该行为是否已经存在;如果存在,应报告这一点,而不要更改生产代码;如果测试没有覆盖到该行为,则修复测试。
- 做出能通过测试的最简单且符合生产要求的改动。不要为后续测试添加行为。
- 运行测试并确认其通过。
- 如果职责归属或内聚性受到影响,就重构修改过的代码,并重新运行测试。
- 根据已获得的认识选择下一个行为。不要一开始就写完所有测试。
对于间歇性错误,应编写确定性的回归测试,并说明测试锁定了什么。如果错误属于更广泛的一类故障,先修复报告中的情况,再考虑同类情况。
保持预期真实可信
只有在需求发生变化、测试不符合需求,或接口变更但受保护的行为保持不变时,才更改测试的预期结果。更改时说明原因。实现产生的新输出绝不是更改预期输出的理由。
这些做法只会让失败的测试变绿,却没有修复行为。请勿使用:
- 更新断言、快照或测试夹具,使其与新输出一致
- 在设置阶段预置真实工作流无法保证的状态,例如标志、回填数据或已初始化的数据
- 模拟掉测试声称要检查的逻辑或集成
- 将错误当作成功,或在需求要求正常工作的路径时,只测试优雅地拒绝请求
- 跳过测试、将其标记为预期失败,或将其排除在运行之外
- 使用与生产代码相同的逻辑计算预期值
如果有效的失败测试需要领域决策、缺失的前置条件,或约定范围以外的工作,就保留测试的失败状态,保留已完成的工作,并报告阻碍因素以及工作尚未完成。若请求仅要求复现 bug,则即使测试仍然失败,也算完成;这并不授权你修复生产代码。
难以执行失败测试时
不要为了遵循流程而搭建大量测试基础设施、运行缓慢的端到端测试环境或复杂的模拟。实施前,先说明限制,并选择其他能展示行为先缺失、后得到修复的检查方式,例如脚本、命令、浏览器工作流或日志检查。如果没有任何检查可以运行,就报告这一缺口。
实现后编写的测试仍能防止回归,但不能证明采用了测试优先的开发方式。如果你在旧代码上运行测试,以证明测试本应失败,请说明这一点。
验证
每个周期都要运行针对性测试和变更附近的测试。如果共享契约或仓库规则有要求,则运行更全面的检查,并在最后运行仓库要求的检查。确认你所依赖的测试确实运行了。命令若因跳过测试而通过,便不能证明任何事情。
最终回复
- 变更前失败的测试或检查及其失败方式,或者说明为何无需测试(一句话)
- 变更后的通过结果,或者仍然失败的测试及其阻碍因素
- 运行的其他检查及其结果
- 如果无法取得变更前失败的证据,说明原因以及采用了哪种检查