O

test-driven-development

作者 obra

一套严格的 test-driven-development(测试驱动开发)工作流,要求先写测试,用 Red-Green-Refactor 循环驱动实现,并在真实项目中避免常见测试反模式。

Stars0
收藏0
评论0
收录时间2026年3月27日
分类测试自动化
安装命令
npx skills add https://github.com/obra/superpowers --skill test-driven-development
概览

概览

这个技能做什么

test-driven-development 技能将严格的 Test-Driven Development(TDD,测试驱动开发)工作流固化成规则:你必须先写一个失败的测试,再写任意生产代码,并在整个过程中遵守严格的 Red-Green-Refactor 循环。

与宽松的“之后再补点测试”不同,这个技能给出的是硬性约束:

  • 没有先失败的测试,就不能写生产代码
  • 必须确认测试是因为正确的原因而失败
  • 只写刚好能让测试通过的最小实现
  • 所有测试变绿后再重构

它还会链接到专门的 testing-anti-patterns 指南,帮助你避免脆弱、误导性的测试。

适用人群

当你符合以下情况时,可以使用 test-driven-development 技能:

  • 你是希望为功能开发、缺陷修复和重构建立可靠流程的 开发者
  • 你的 团队 正在统一采用 TDD,需要一套所有人都能遵循的清晰规则
  • 你是 教练或技术负责人,希望团队形成一致的自动化测试习惯

它对 JavaScriptTypeScript 代码库尤其有帮助,但其原则适用于任何语言和测试框架。

解决的痛点

这个技能主要用于解决日常开发中常见的问题:

  • 先写代码,测试要么之后再补,要么干脆没有
  • 不确定测试是否真的验证了行为
  • 因为测试薄弱或缺失而不敢重构
  • 滥用或误用 mocks,只测“假行为”而不是实际行为

通过遵循 test-driven-development 工作流,你可以:

  • 从失败的测试中获得 快速反馈
  • 留下清晰的 预期行为记录
  • 通过测试锁定行为,让 重构更安全
  • 避免只验证 mocks 或实现细节的脆弱测试

何时使用(以及何时不必)

上游技能明确建议在以下场景使用 TDD:

  • 新功能开发
  • 缺陷修复
  • 重构工作
  • 任何行为变更

同时也列出了需要与你的人类搭档讨论的例外情况,例如:

  • 一次性抛弃的原型
  • 自动生成的代码
  • 配置文件

如果你只是“随便探索”或者做一个很快就会丢弃的 spike,这种严格的 test-driven-development 技能可能显得有点重。但对于正式上线的功能,它被设计为 默认工作流,而不是可选附加项。

使用方式

安装

要从 obra/superpowers 仓库安装 test-driven-development 技能,运行:

npx skills add https://github.com/obra/superpowers --skill test-driven-development

这会将 test-driven-development 的技能定义和支持文件拉取到你的 Agent Skills 环境中。安装完成后,你可以打开该技能的文件,查看详细规则和反模式示例。

这个技能会引用的关键文件包括:

  • SKILL.md – 核心 TDD 规则,包括 Iron Law 和 Red-Green-Refactor
  • testing-anti-patterns.md – 聚焦于测试中 不要 做什么的指南

核心原则:Iron Law

这个技能的核心是其源头定义的 Iron Law

NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST

落到实操上:

  • 如果你在测试之前写了生产代码,就必须 删掉这段代码,然后从测试开始重来
  • 不能 把这段代码留作“参考”,一边保留一边写测试
  • 在基于测试重新实现时,不能 偷看刚删掉的那份代码

这条硬性规则确保每一行生产代码都由真实的测试驱动产生。

分步 TDD 工作流

安装 test-driven-development 技能后,可以把它当作你的默认工作流来执行:

1. 写一个会失败的测试(RED)

  • 明确一个 单一行为(功能、缺陷修复或重构的预期结果)
  • 写一个 新的测试,表达你期望的行为
  • 运行测试,确认这个新测试确实失败

在 RED 步骤结束之前,你必须:

  • 亲眼看到测试失败
  • 确认它是因为 正确的原因 而失败(正确的断言、正确的错误)

如果失败原因不对(例如测试在 setup 阶段崩溃),就要修正测试并重新运行,直到它以有意义的方式失败为止。

2. 写最少代码让测试通过(GREEN)

  • 只实现 让当前失败测试通过所需的最简单代码
  • 避免过早设计、抽象或多余逻辑
  • 运行整个测试集,确保新测试变为 green,且已有测试仍全部通过

这个步骤的指导刻意保持收敛:“完成整个功能”不是当前目标,你的目标是 满足测试

3. 安全地重构(REFACTOR)

当所有测试都为 green 时:

  • 清理生产代码:去重、简化逻辑、优化命名
  • 清理测试代码:提升可读性,必要时抽取 helper
  • 频繁运行测试,确保行为未发生改变

在测试集的保护下,你可以在保持行为不变的前提下改进设计。

4. 重复循环

对每一个小行为或边界情况:

  • 再添加一个测试(RED)
  • 让它通过(GREEN)
  • 按需重构(REFACTOR)

test-driven-development 技能的作用,就是把你牢牢锁在这个循环中,让“跳过某一步”变得难以自我说服。

与现有技术栈集成

仓库中的示例主要聚焦 JavaScriptTypeScript,但你可以在任何技术栈中应用相同的 TDD 规则:

  • JavaScript/TypeScript 项目中(如使用 Jest、Vitest 或 Mocha):

    • 在修改生产文件之前,务必先创建或修改测试(如 *.test.ts*.spec.ts
    • 对每一次应用代码改动,围绕它执行完整的 Red-Green-Refactor 循环
  • 在其他语言(如 Python、Java、Go、C#)中:

    • 将相同步骤映射到你的测试框架(pytest、JUnit、Go test、xUnit 等)
    • 那条严格的规则——“no production code without a failing test”——同样适用

这个技能本身不会把你锁死在某个具体框架上;它固化的是 工作流规则,而不是依赖某个 library。

使用 testing anti-patterns 指南

附带的 testing-anti-patterns.md 文件是 test-driven-development 技能的配套指南。在以下场景时,建议加载或参考它:

  • 编写或修改测试时
  • 添加 mocks 或 stubs 时
  • 想往生产类或模块里加只用于测试的 hook 时

这份指南中的关键原则包括:

  • 不要测试 mock 的行为 —— 测试应验证真实行为,而不是“某个 mock 存在”
  • 不要给生产类添加仅用于测试的方法 —— 保持生产 API 的干净与内聚
  • 不要在没搞清依赖关系前乱用 mock —— 过度 mocking 会制造虚假的安全感

指南中的反模式示例使用 TypeScript 风格的测试演示 bad vs good,你可以据此适配到自己的测试框架中。

将工作流适配到你的团队

安装之后,你可以在保持核心意图不变的前提下,把 test-driven-development 技能的规则调整到适配团队实际情况:

  • 对齐哪些类型的改动 必须 严格按 TDD 执行(如所有生产模块、领域核心逻辑、关键业务流)
  • 明确少数例外场景(如快速 spike 或生成代码),但要保持清晰透明
  • 把 Iron Law 融入 code review 清单:
    • “这次改动对应的失败测试在哪里?”
    • “测试是不是先写的?”

这样,你就能把这个技能用作 团队级标准,而不只是个人习惯。

常见问题(FAQ)

test-driven-development 技能是否依赖特定测试框架?

不会。test-driven-development 技能定义的是一套 工作流和规则,而不是某个具体测试框架。仓库里的示例偏向 JavaScript 和 TypeScript,但同样的 Red-Green-Refactor 循环可以在任何语言中使用。

我真的必须删掉那些没有测试就写出来的代码吗?

按照 SKILL.md 中的 Iron Law 要求,是的。如果你在失败测试之前就写了生产代码,规则就是 删掉它,然后从测试开始重写。这样可以杜绝把测试当作“事后补救”的心态。

在哪些情况下不太适合使用这个技能?

上游的指导列出了一些可能的例外,比如一次性原型、生成代码或配置文件。对于短命的探索性 spike,严格的 test-driven-development 可能显得过重。而对于面向生产的功能、缺陷修复和重构,这个技能是推荐的默认选择。

这个技能如何帮助调试和重构?

在修复 bug 或做重构时:

  • 先写一个失败测试,复现 bug 或明确预期行为
  • 然后修改代码,直到测试通过
  • 最后在测试保护下进行重构,因为测试会约束既有行为

这会让调试更系统化,也让重构变得更安全可控。

这个技能能在没有测试的遗留代码上用吗?

可以,但通常需要 渐进式 应用:

  • 每当你接手一块遗留代码,先添加一个测试,捕获当前行为或期望行为
  • 如果你要修改行为,让测试先失败,然后再让它通过
  • 利用 Red-Green-Refactor 循环,逐步让这一块代码进入“有测试保护”的状态

时间久了,你会有越来越多的遗留代码被测试覆盖保护。

安装之后,我应该从哪里开始?

运行安装命令之后,可以先打开:

  • SKILL.md:查看核心 test-driven-development 规则和 Red-Green-Refactor 的详细说明
  • testing-anti-patterns.md:了解编写测试时常见的坑和反模式

把这两个文件当作你日常开发工作流的参考手册来使用。

评分与评论

暂无评分
分享你的评价
登录后即可为这个技能评分并发表评论。
G
0/10000
最新评论
保存中...