mcpField
T
tdd

tdd

github.com/hburaktasyurek测试与质量049 次安装4 周前更新
代码仓库

关于 tdd

tdd 是一项跨语言和测试框架的测试驱动开发 Agent 技能,强调通过稳定边界验证可观察行为。它采用逐项 RED–GREEN 循环,并要求在改代码前厘清需求约定。

主要功能

  1. 01在稳定边界测试可观察行为
  2. 02逐项执行 RED–GREEN 循环
  3. 03遵循项目语言与测试惯例
  4. 04编辑前检查需求约定
  5. 05覆盖失败场景和边界情况

适用场景

  1. 01逐步开发功能
  2. 02复现并修复已报告的问题
  3. 03避免测试依赖实现细节
  4. 04区分回归与既有测试失败

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/hburaktasyurek/agent-skills-and-commands --skill tdd

安装后在 Claude Code 中输入/tdd确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

deep-modules.md
interface-design.md
mocking.md
refactoring.md
tests.md
agents/
openai.yaml

详细介绍

测试驱动开发

理念

核心原则:测试应通过最稳定的可用契约边界验证可观察行为,而不是验证偶然的实现细节。代码可以彻底改变;除非行为发生变化,否则测试不应失败。

好的测试采用集成测试风格:通过公共 API 执行真实代码路径。它们描述系统_做什么_,而不是_如何_实现。好的测试读起来就像一份规范——“用户可以使用有效购物车完成结账”准确说明了系统具备什么能力。这类测试能经受重构,因为它们不关心内部结构。

糟糕的测试与实现耦合。它们模拟内部协作者、测试私有方法,或断言偶然的调用顺序。警示信号:仅仅重命名或调整不影响行为的内部结构,测试就会失败。

公共响应并不总是充分的证据。持久化、幂等性、并发、队列和恢复契约可能需要启动新进程、使用独立连接、在提交后读取,或断言持久状态。如果这类证据属于可观察契约,就应使用它;不要用成功响应或模拟交互代替真正的不变量。

参见 tests.md 了解示例,参见 mocking.md 了解模拟指南。

语言与工具

这里的原则——关注行为而非实现、仅在系统边界进行模拟、深模块——与语言无关。示例仅用于说明,使用的是 TypeScript/Jest。**编写任何测试前,先检测项目所用的语言、测试运行器、断言风格和模拟约定,并遵循这些约定。**转换原则,而不是语法:Python 项目使用 pytest 的惯用写法和 fixtures,PHP 项目遵循 PHPUnit 约定,JS/TS 项目使用现有的测试运行器(Jest/Vitest/node:test)。不要将某种语言的惯用写法带入未使用它的项目。

反模式:水平切片

**不要先写完所有测试,再写完所有实现。**这就是“水平切片”——把 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
  ...

契约关卡

编辑前,先阅读仓库说明和权威任务、简报、规范或审查发现。检查足够多的实现与测试,以判断契约是否已准备就绪。

  • 如果行为、范围、公共接口、验收标准和决策权均已明确,就将其视为已获批准,并开始第一个 RED 周期。不要要求用户再次确认计划,或重复已有产物中已经作出的决定。
  • 如果技术细节不会改变产品行为或范围,就根据仓库证据解决。
  • 如果产物相互冲突,或仍有重要的行为、范围、接口、优先级或决策权尚未确定,就不要写入仓库。报告证据冲突,并提出一个具体的阻塞性问题。
  • 如果直接请求具有权威性且内容完整,不要因为缺少流程形式——例如工单、路线图或单独的测试计划——就将其作为阻塞因素。

列出为实现因果闭环所需的最小有序行为集,包括失败模式和边界。将其作为执行指南;除非契约关卡发现确实需要人工决策的问题,否则不要暂停等待批准。

工作流

1. 首先 RED

对于功能,请从已批准的契约中选择最精简的端到端行为。对于 Bug,先在能够证明 Bug 的边界复现所报告的故障。

编写一个聚焦的测试并运行。只有当测试因预期缺失或错误的行为而失败时,RED 才有效。语法错误、损坏的测试夹具、不可用的依赖项或无关的既有故障都不能作为有效的 RED;应修复测试设置,或报告外部阻碍,不要更改产品代码。

你无法测试所有内容,但“关键行为”包括系统如何失败,而不仅仅是成功路径。 根据权威契约和仓库风险证据确定优先级。将错误处理、无效输入、边界条件和故障模式视为一等行为。只有在契约关卡发现真正尚未解决的决策时,才询问用户。跳过琐碎的排列组合,而不是不同的异常路径。

2. GREEN

实施最小且从根本上正确的更改,使聚焦的行为通过,同时不违反已知契约。“最小”并不意味着只修补报告问题的那一行,却让同一因果路径仍然敞开。

RED:   Write test for first behavior → test fails
GREEN: Write minimal code to pass → test passes

这是你的示踪弹,证明该路径能够端到端运行。

继续之前,运行聚焦的测试并确认 GREEN。

3. 增量循环

对于每项剩余行为:

RED:   Write next test → fails
GREEN: Minimal code to pass → passes

规则:

  • 一次只编写一个测试
  • 只编写足以通过当前测试的代码
  • 不要预先考虑未来的测试
  • 让测试聚焦于可观察的行为
  • 根据上一轮中获得的证据添加下一个测试
  • 在宣称完成之前,覆盖任务涉及的成功、失败、边界及同根因回归场景
4. 重构

所有测试通过后,查找重构候选项:

  • 提取重复代码
  • 深化模块(将复杂性移至简单接口之后)
  • 在适当时应用 SOLID 原则
  • 思考新代码揭示了现有代码的哪些问题
  • 每一步重构后都运行测试

RED 时绝不重构。 先达到 GREEN。

聚焦测试循环全部通过后,运行相关的更大范围测试套件。将无关的既有故障与任务引入的回归区分开;不要悄悄修复或掩盖无关故障。

每轮检查清单

[ ] Test describes behavior, not implementation
[ ] Test uses the stable observable boundary
[ ] Test would survive internal refactor
[ ] RED failed for the expected reason
[ ] Code is minimal for this test
[ ] No speculative features added

评论

支持 Markdown