tdd

SKILL.md

测试驱动开发(TDD)

哲学(Philosophy)

核心原则:测试应当通过公共接口验证行为,而不是依赖实现细节。代码可以被完全重写;测试不应该随之频繁改变。

好的测试具有集成式特征:它会通过公共 API 实际跑通真实代码路径。它描述系统“做什么”,而不是“怎么做”。好的测试读起来像规范——例如“用户在使用有效购物车时可以结账”,你就能明确知道系统具备这个能力。由于测试不关心内部结构,它能在重构后继续存活。

坏的测试会耦合到实现。它们 mock 内部协作者、测试私有方法,或用“绕过接口”的方式验证(例如直接查询数据库而不是使用接口)。危险信号是:当你重构但行为没有变化时,测试却失败了;如果你重命名了某个内部函数导致测试失败,但用户可观察行为却没有变,这些测试是在测实现而不是在测行为。

查看 tests.md 获取更多示例,并查看 mocking.md 了解 mock 指南。

反模式:横向切片(Horizontal Slices)

不要写“先写完所有测试,再写所有实现”。

这是一种“把 RED 当成写所有测试”的横向切片:把 RED 理解成“先写完所有测试”,把 GREEN 理解成“一次性写完所有代码”。

这会产生 烂测试(crap tests),包括:

  • 大量批量编写的测试验证的是“想象出来的行为”,而不是“真实的行为”
  • 测试会变成在测“结构形状”(数据结构、函数签名),而不是用户可见的行为
  • 测试会对真实变化变得不敏感:行为坏了反而测试仍可能通过;行为没坏时反而会失败
  • 你会在还没理解实现之前就“把车灯开出来”,过早承诺测试结构

正确做法:通过 tracer bullets 进行竖向切片(vertical slices)。一个测试 → 一个实现 → 重复。每一轮测试都会基于上一轮你从代码/理解中学到的东西来推进。由于你刚刚写完代码,所以你会非常清楚“哪些行为重要”以及“用什么方式验证它”。

WRONG(横向):
  RED:   test1, test2, test3, test4, test5
  GREEN: impl1, impl2, impl3, impl4, impl5

RIGHT(竖向):
  RED→GREEN: test1→impl1
  RED→GREEN: test2→impl2
  RED→GREEN: test3→impl3
  ...

工作流(Workflow)

1. 规划(Planning)

在写任何代码之前:

  • 与用户确认需要如何修改接口(interface changes)
  • 与用户确认需要测试哪些行为(优先级更高)
  • 识别可以提取的 深模块(deep modules)(小接口、深实现)
  • 可测试性(testability) 设计接口
  • 列出要测试的行为(而不是实现步骤)
  • 让用户批准该计划

提问:公共接口应当长什么样?哪些行为最重要、最需要先测?

你无法把所有东西都测完。 请与用户明确“哪些行为最关键”。把测试资源集中在关键路径与复杂逻辑上,而不是覆盖所有可能的边界情况。

2. tracer bullet(示踪子弹)

写出 一个测试,用来确认系统的 一个要点:

RED:   为第一个行为写测试 → 测试失败
GREEN: 写最小代码让测试通过 → 测试通过

这就是你的 tracer bullet——它证明这条路径能端到端跑通。

3. 逐步循环(Incremental Loop)

对剩余的每个行为:

RED:   写下一个测试 → 失败
GREEN: 最小实现让它通过 → 通过

规则:

  • 一次一个测试
  • 只写足够通过当前测试的代码
  • 不要提前为未来测试“预埋”
  • 保持测试聚焦在可观察的行为

4. 重构(Refactor)

当所有测试都通过之后,再查看 重构候选(refactoring.md)

  • 抽取重复逻辑
  • 加深模块(把复杂度移到简单接口背后)
  • 在自然的地方应用 SOLID 原则
  • 评估新代码暴露出的、对现有代码的潜在问题
  • 每完成一个重构步骤就运行测试

不要在 RED 状态下重构。 先到 GREEN 再谈重构。

每一轮循环的清单(Checklist Per Cycle)

[ ] 测试描述的是行为,而不是实现
[ ] 测试只使用公共接口
[ ] 测试在内部重构后仍能存活
[ ] 针对该测试的代码足够最小
[ ] 没有加入“为了以后而猜”的功能
Weekly Installs
3
GitHub Stars
135
First Seen
10 days ago
Installed on
opencode3
deepagents3
antigravity3
claude-code3
github-copilot3
codex3