---
name: tdd
description: >
  Red-Green-Refactor 测试驱动开发纪律。
  Use when: 写新功能代码、修 bug、任何实现工作。
  Not for: 纯文档、纯调研、已有充分测试的 trivial 改动。
  Output: 失败测试 → 最小实现 → 重构，全程有测试保护。
triggers:
  - "写代码"
  - "test first"
  - "TDD"
  - "红绿重构"
---

# TDD（测试驱动开发）

先写测试。看它失败。写最少代码通过。

**铁律：没有失败的测试，就没有实现代码。**

## 核心知识

### 为什么顺序绝对不能反？（4 个常见异议的反驳）

| 异议 | 真相 |
|------|------|
| "写完再补测试，也能验证" | 测试写在实现后会立即通过——你永远不知道它是否真的在测你要的东西 |
| "我手工测了所有 case" | 手工测试没有记录、不能重跑、下次改动时你会忘了测什么 |
| "删掉 X 小时的工作太浪费" | 沉没成本谬误。留着无法信任的代码才是浪费 |
| "TDD 是教条，务实应该灵活" | TDD 本身就是务实的——它比事后调试快，能防止回归，是真正的捷径 |

**Tests-after 回答"这段代码做了什么"；tests-first 回答"这段代码应该做什么"。两者不等价。**

### Red-Green-Refactor 循环

```
RED  → 写一个会失败的测试
       ↓ 必须亲眼看到它失败（失败原因要对，不是 typo）
GREEN → 写最少代码让测试通过
       ↓ 必须亲眼看到它通过（其他测试也要绿）
REFACTOR → 消除重复、改善命名
       ↓ 保持绿灯，不添加行为
重复 →
```

**关键决策点**：
- RED 阶段测试立即通过？→ 你在测已有行为，修测试
- RED 阶段报错而非失败？→ 修错误直到"正确地失败"
- GREEN 阶段其他测试挂了？→ 立即修，不要继续
- REFACTOR 后测试变红？→ 撤销 refactor，重来

### Bug Fix 模式

Bug 修复和新功能一样，必须先写失败测试。**入口动作：先填诊断胶囊。**

> 诊断胶囊模板 → [refs/bug-diagnosis-capsule.md](../refs/bug-diagnosis-capsule.md)

```bash
# 0. 填诊断胶囊（现象/证据/假设/诊断策略/超时策略/预警策略）
# 1. 写一个复现 bug 的测试（此时必须红）
# 2. 确认测试以"预期的理由"失败
# 3. 修复代码
# 4. 确认测试通过 → 填胶囊第 8 栏（验收）
# 5. 确认无回归
```

**永远不要在没有测试的情况下修 bug。**

## 流程

```
任务开始
  ↓
写一个描述期望行为的测试
  ↓
跑测试 → 失败？→ 继续
              → 通过？→ 你在测已有行为，修测试
  ↓
写最少实现代码
  ↓
跑测试 → 通过？→ 继续
              → 失败？→ 修代码（不改测试）
  ↓
全量测试通过？→ Refactor → 重复
```

## Quick Reference

### 好测试的标准

- **一个行为**：名字里有"and"？拆分
- **名字描述行为**：`rejects empty email` 好于 `test1`
- **测真实代码**：避免只测 mock

### 口令：立即停止的 Red Flags

听到自己说以下任何一句 → 删掉代码，从测试重新开始：

- "应该能过"、"大概没问题"、"先快速实现一下"
- "测试我写完功能再补"、"这个太简单了不用测"
- "我已经手工验证过了"、"精神一致就够了，不用走形式"
- "这个情况不一样，因为……"、"留着参考，写测试时再删"

**所有这些都是理由化（Rationalization）。没有例外。**

## Common Mistakes

| 错误 | 正确做法 |
|------|----------|
| 先写实现，再补测试 | 删掉实现，从失败测试开始 |
| 跳过"看它失败"步骤 | 必须跑测试亲眼看失败 |
| 测试立即通过就继续 | 停下来——测试没有测到真正的行为 |
| 修 bug 时直接改代码 | 先写复现 bug 的失败测试 |
| GREEN 阶段过度实现 | 只写能通过当前测试的最少代码 |
| mock 了所有东西 | 代码耦合度太高，用依赖注入简化 |

## 和其他 skill 的区别

- **vs `debugging`**：TDD 是**预防性**的（写代码前）；debugging 是**修复性**的（bug 出现后）。两者的交叉点：debugging 发现 bug 后，Phase 4 必须先写失败测试再修（此时切换回 TDD 模式）
- **vs `quality-gate`**：TDD 是开发过程中的纪律；quality-gate 是提交前的验收检查

## 下一步

完成功能实现后 → **直接加载 `quality-gate`** 做提交前验收。不要停下来问铲屎官（§17）。
