# Tdd Coach

> 指导测试驱动开发，遵循红-绿-重构循环来编写聚焦行为的测试和最小化实现。当用户希望以TDD方式开发功能或修复Bug、提到"红绿重构"、需要进行集成测试、或要求测试先行开发时使用。

- Skill: `haomingz/tdd-coach` (Agent Skill, multi-file: 7 files)
- Install (CLI): `npx skillmds@latest add haomingz/tdd-coach`
- Raw SKILL.md: https://api.skillmd.com/api/skills/haomingz/tdd-coach/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: haomingz (https://skillmd.com/u/haomingz)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/haomingz/tdd-coach

---


# 测试驱动开发

## 核心理念

**基本原则**：测试应该通过公开接口验证行为，而不是验证实现细节。代码可以完全重写，但测试不应因此而变。

**好的测试**是集成风格的：它们通过公开 API 执行真实的代码路径。好的测试描述的是系统"做什么"，而不是"怎么做"。一个好的测试读起来就像一份规格说明——"用户可以用有效购物车结账"清楚地说明了系统具备什么能力。这样的测试能在重构中存活下来，因为它们不关心内部结构。

**坏的测试**与实现耦合。它们 mock 内部协作者、测试私有方法、或通过外部手段（比如直接查询数据库而不是使用接口）来验证。一个危险信号是：你重构了代码，测试却挂了，但行为并没有变。如果你重命名了一个内部函数导致测试失败，说明那些测试测的是实现，不是行为。

参见 [tests.md](tests.md) 了解示例，以及 [mocking.md](mocking.md) 了解 mock 使用指南。

## 反模式：水平切片

**不要先写完所有测试，再写所有实现。** 这就是"水平切片"——把红色阶段当成"写所有测试"，绿色阶段当成"写所有代码"。

这样会写出**糟糕的测试**：

- 批量写的测试测的是_想象中的_行为，而不是_实际的_行为
- 你最终测的是_数据结构的形状_（数据结构、函数签名），而不是面向用户的行为
- 测试对真正的变化不敏感——行为坏了测试却通过，行为没问题测试却失败
- 你跑在了前灯之前，在理解实现之前就绑定了测试结构

**正确做法**：通过"示踪弹"做垂直切片。写一个测试 → 写一个实现 → 循环。每个测试都基于上一轮循环中学到的东西。因为你刚写完代码，你清楚地知道哪些行为重要、如何验证。

```
错误（水平切片）：
  红：   test1, test2, test3, test4, test5
  绿：   impl1, impl2, impl3, impl4, impl5

正确（垂直切片）：
  红→绿：test1→impl1
  红→绿：test2→impl2
  红→绿：test3→impl3
  ...
```

## 工作流程

### 1. 规划

在写任何代码之前：

- [ ] 与用户确认需要哪些接口变更
- [ ] 与用户确认要测试哪些行为（确定优先级）
- [ ] 识别适合做[深模块](deep-modules.md)的机会（小接口，深实现）
- [ ] 为[可测试性](interface-design.md)设计接口
- [ ] 列出需要测试的行为（不是实现步骤）
- [ ] 获得用户对计划的确认

要问："公开接口应该是什么样的？哪些行为最重要、需要测试？"

**你不可能测试所有东西。** 与用户确认哪些行为最关键。把测试精力集中在关键路径和复杂逻辑上，而不是每个可能的边界情况。

### 2. 示踪弹

写一个测试，验证系统的一个行为：

```
红：   写第一个行为的测试 → 测试失败
绿：   写最少的代码让测试通过 → 测试通过
```

这就是你的示踪弹——证明这条路径端到端是通的。

### 3. 增量循环

对每个剩余的行为：

```
红：   写下一个测试 → 失败
绿：   写最少代码让它通过 → 通过
```

规则：

- 一次只写一个测试
- 只写刚好让当前测试通过的代码
- 不要预判未来的测试
- 保持测试聚焦在可观察的行为上

### 4. 重构

所有测试通过后，寻找[重构候选](refactoring.md)：

- [ ] 提取重复代码
- [ ] 加深模块（把复杂性藏在简单接口后面）
- [ ] 在自然的地方应用 SOLID 原则
- [ ] 思考新代码揭示了已有代码的什么问题
- [ ] 每次重构后运行测试

**绝不在红色阶段重构。** 先到绿色阶段。

## 每轮循环检查清单

```
[ ] 测试描述的是行为，不是实现
[ ] 测试只使用公开接口
[ ] 测试能在内部重构中存活
[ ] 代码是针对当前测试的最小实现
[ ] 没有添加推测性的功能
```

