# Lesson 22: 测试与代码审查：质量保障三板斧

## 本课目标

- 掌握 /tdd 的 RED→GREEN→REFACTOR 循环和 80% 覆盖率标准
- 理解 /e2e 端到端测试如何验证完整用户旅程
- 学会 /code-review 的安全和质量审查标准
- 理解 /build-fix 如何自动修复构建错误

## 核心内容

### 重要前提：通用实现不是最终方案

本课介绍的 `/tdd`、`/e2e`、`/code-review`、`/build-fix` 是面向教学流程的**通用实现**，目的是帮助你理解质量保障的基本结构和协作顺序。

在真实项目中，不要机械照搬这些默认流程，而要根据自己的技术栈、业务风险、团队成熟度和交付节奏进行优化。例如：金融、医疗、支付等高风险业务需要更高覆盖率和更严格的审查标准；早期 MVP 项目则可以优先保障核心用户旅程，避免把时间耗在低价值边界上。

你真正要掌握的不是某个固定命令模板，而是这套判断逻辑：**先定义什么叫做对，再让 AI 写代码，最后用测试、审查和真实用户旅程验证结果。**

### 质量保障的三层防线

```
第一层：/tdd（开发时）
  ↓ 在写代码的同时写测试，确保每个功能都有验证

第二层：/code-review（提交前）
  ↓ 安全检查 + 代码质量 + 最佳实践审查

第三层：/e2e（集成后）
  ↓ 模拟真实用户操作，验证完整流程
```

### /tdd —— 测试驱动开发

**核心思想**：先写测试，再写代码。不是"写完代码补测试"，而是"用测试定义成功标准"。

**为什么 TDD 比先写代码好？**

```
传统开发：
  写功能代码 → 手动测试 → 发现 Bug → 修复 → 手动测试
  问题：手动测试不完整，Bug 在上线后被用户发现

TDD：
  写测试（定义"对"的标准）→ 写代码（让测试通过）→ 重构
  优势：每个功能都有自动验证，Bug 在开发时就被发现
```

#### RED→GREEN→REFACTOR 循环

```bash
/tdd
```

```
TDD Guide：开始 TDD 循环。

═══════════════════════════════════
SCAFFOLD（脚手架）
═══════════════════════════════════
先定义接口和类型——还不写任何实现。

interface Calculator {
  add(a: number, b: number): number;
  divide(a: number, b: number): number;
}

═══════════════════════════════════
RED（红灯——写失败的测试）
═══════════════════════════════════
写测试，这些测试现在一定会失败：

test('add(1, 2) should return 3', () => {
  expect(calculator.add(1, 2)).toBe(3);
});
test('divide(6, 0) should throw', () => {
  expect(() => calculator.divide(6, 0)).toThrow();
});

运行测试... ❌ 2 个失败（预期！）

═══════════════════════════════════
GREEN（绿灯——写最少代码通过测试）
═══════════════════════════════════
只写让测试通过的最少代码：

function add(a, b) { return a + b; }
function divide(a, b) {
  if (b === 0) throw new Error('Division by zero');
  return a / b;
}

运行测试... ✅ 2 个通过

═══════════════════════════════════
REFACTOR（重构——保持绿灯优化代码）
═══════════════════════════════════
优化代码结构，测试必须保持通过。

运行测试... ✅ 仍然 2 个通过
覆盖率：92% ✅（目标：80%+）
```

#### 覆盖率标准

| 代码类型 | 最低覆盖率 | 原因 |
|---------|-----------|------|
| 普通业务代码 | 80% | 合理的投入产出比 |
| 财务计算 | 100% | 算错一分钱都是 Bug |
| 认证/授权 | 100% | 安全漏洞不可接受 |
| 核心业务逻辑 | 100% | 这是产品的核心价值 |

#### 需要关注的 TDD 信号

```
✅ 健康信号：
  "覆盖率 85%，所有测试通过"
  "新增 12 个测试，覆盖了 3 个边界情况"

⚠️ 警告信号：
  "覆盖率 65%，未达标"
  "跳过了 3 个测试"

❌ 危险信号：
  "没有写测试就提交了"
  "测试在本地通过但 CI 失败"
```

### /e2e —— 端到端测试

**核心思想**：模拟真实用户的完整操作路径，验证整个系统（前端+后端+数据库）是否正常工作。

```bash
/e2e
```

**和单元测试的区别**：

```
单元测试（/tdd）：
  测试一个函数：add(1, 2) === 3 ？
  范围：单个函数或组件
  速度：毫秒级

端到端测试（/e2e）：
  测试一个用户旅程：
  "用户打开登录页 → 输入账号 → 点击登录 → 看到首页"
  范围：整个系统
  速度：秒级（真实浏览器）
```

#### E2E 测试流程

```
Step 1: 分析用户流程，识别测试场景
        ↓ 例：登录、注册、记账、生成报表

Step 2: 生成 Playwright 测试代码
        ↓ 使用 Page Object Model 模式
        ↓ 使用 data-testid 选择器（不用脆弱的 CSS）

Step 3: 多浏览器执行
        ↓ Chrome + Firefox + Safari + Mobile

Step 4: 失败时自动捕获证据
        ↓ 截图、视频、网络日志、Trace 文件

Step 5: 生成 HTML 报告
        ↓ 测试结果 + 失败原因 + 截图
```

#### 连接 WDS 场景到 E2E 测试

WDS 阶段（L19）创建的 UX 场景，每个步骤都能直接映射为 Playwright 测试断言：

```
WDS 场景: "打开App → 点'+' → 拍发票 → AI分类 → 确认"
    ↕ 一一对应
E2E 测试: page.goto → click → setInputFiles → expect → click
```

**前面设计阶段的产出（UX 场景），就是后面测试阶段的输入。** 这就是 cc4pm 全流程的价值——每个阶段的知识被下一个阶段复用，而不是从零开始。

### /code-review —— 代码审查

**核心思想**：在代码提交之前，自动检查安全漏洞、代码质量和最佳实践。

```bash
/code-review
```

#### 审查的四个级别

```
CRITICAL（立即阻止提交）：
  ❌ 硬编码的密钥/密码/Token
  ❌ SQL 注入漏洞
  ❌ XSS 跨站脚本攻击
  ❌ 缺少输入验证
  ❌ 不安全的依赖

HIGH（建议修复后再提交）：
  ⚠️ 函数超过 50 行
  ⚠️ 文件超过 800 行
  ⚠️ 嵌套超过 4 层
  ⚠️ 缺少错误处理
  ⚠️ 留有 console.log
  ⚠️ TODO/FIXME 注释
  ⚠️ 公共 API 缺少文档

MEDIUM（建议优化）：
  💡 可以用不可变写法
  💡 新代码缺少测试
  💡 可访问性问题

LOW（建议参考）：
  📝 命名风格不一致
  📝 代码格式问题
```

#### 需要关注的审查结果

```
收到审查报告后，你应该关注：

CRITICAL 问题 → 必须修复才能上线
  "发现硬编码的 API Key" → 安全事件！
  "SQL 注入漏洞" → 数据泄露风险！

其他问题 → 可以和开发讨论优先级
  "函数太长" → 可以下个迭代优化
```

### /build-fix —— 自动修复构建错误

**核心思想**：当代码编译/构建失败时，自动检测错误、逐个修复、验证修复结果。

```bash
/build-fix
```

**工作流程**：

```
Step 1: 检测构建工具
        ↓ npm/pnpm? TypeScript? Go? Python? Rust?

Step 2: 捕获错误信息
        ↓ 解析 stderr，按文件分组

Step 3: 逐个修复（最小化修改原则）
        ↓ 读取错误上下文 → 诊断根因 → 最小修复 → 重新构建验证

Step 4: 安全护栏
        ↓ 如果修复引入新错误 → 停止
        ↓ 如果 3 次尝试失败 → 上报
        ↓ 如果需要架构变更 → 请求人工介入
```

**实用提示**：构建失败时直接跑 `/build-fix`，它会自动检测错误、诊断根因、最小修复。如果 3 次尝试失败，再考虑手动排查。

### 四个命令的协作关系

```
开发一个新功能的完整流程：

/plan     "我要做什么？怎么做？有什么风险？"
  ↓ 确认方案
/tdd      "先定义测试——'做对了'长什么样？"
  ↓ RED → GREEN → REFACTOR
/build-fix "编译出错了？自动修。"
  ↓ 构建通过
/code-review "代码安全吗？质量好吗？"
  ↓ 修复 CRITICAL/HIGH 问题
/e2e      "用户能正常使用吗？"
  ↓ 所有用户流程通过
git commit → PR → 合并到主分支
```

### 为什么文档先行和测试先行？

上面四个命令的顺序不是随意的——它反映了一个更深层的认知。

ThoughtWorks 的徐昊说过：**软件工程本质上是知识工程，软件是知识的实践和传递。** 这句话在 AI 时代变得更加真实。

```
AI 写代码几乎毫不费力。
  → 代码不再是稀缺资源。
  → 稀缺的是"知道要写什么"和"确认写对了没有"。

人类负责把关的两件事：
  ① 文档先行 — 知道要写什么（输入端知识）
  ② 测试先行 — 确认写对了没有（输出端验证）
```

**文档先行**——/plan 的本质。PRD、Story、验收标准，这些都是在编码之前把"知识"固化下来。没有文档，你给 AI 的指令就是模糊的，它猜出来的结果大概率不是你想要的。CLAUDE.md（Lesson 5）也是文档先行：你把项目的"知识"写下来，AI 才能按照你的期望工作。

**测试先行**——/tdd 的本质。RED→GREEN→REFACTOR 的精髓不是"写测试"，而是**先定义"对"的标准**。当你先写测试时，你是在把脑子里"正确应该长什么样"这个知识显式化。AI 看到测试就知道目标，比看到模糊的需求描述准确 10 倍。

```
传统思维：
  代码 = 核心资产
  文档和测试 = 附属品

AI 时代思维：
  知识（文档 + 测试） = 核心资产
  代码 = 知识的可执行表达
```

**这意味着什么？** 作为产品主理人，你的核心竞争力不是写代码——AI 比你快 100 倍。你的核心竞争力是：
- **知道要做什么**（需求洞察 → 文档化 → /plan）
- **知道什么算对**（验收标准 → 测试化 → /tdd）
- **判断最终结果是否正确**（质量把关 → /code-review + /e2e）

/cc4pm 的整个工程流程，本质上就是**知识工程的最佳实践**——用文档捕获"做什么"，用测试捕获"对不对"，让 AI 负责中间的"怎么做"。

## 🛠️ 实操练习

完成以下练习，掌握测试与代码审查工具。

### 练习 1：使用 /tdd 进行测试驱动开发

```bash
# 启动 TDD 工作流
/tdd
```

**任务**：
1. 选择一个简单的功能（如"邮箱格式验证"）
2. 按照 RED → GREEN → REFACTOR 流程
3. 先写失败的测试，再写实现代码

**预期产出**：
- 测试文件（覆盖率 ≥ 80%）
- 通过测试的实现代码

### 练习 2：使用 /code-review 进行代码审查

```bash
# 运行代码审查
/code-review
```

**任务**：
- 对一段代码运行四级审查
- 查看 CRITICAL/HIGH/MEDIUM/LOW 分类
- 理解每个问题的修复建议

**审查级别说明**：

| 级别 | 含义 | 处理方式 |
|------|------|---------|
| CRITICAL | 安全漏洞/数据丢失 | 必须立即修复 |
| HIGH | 严重 Bug/性能问题 | 合并前必须修复 |
| MEDIUM | 代码质量问题 | 建议修复 |
| LOW | 风格建议 | 可选修复 |

### 练习 3：使用 /e2e 进行端到端测试

```bash
# 运行 E2E 测试
/e2e
```

**任务**：
- 为核心用户旅程创建 E2E 测试
- 使用 Playwright 运行测试
- 查看测试报告

### 练习 4：使用 /build-fix 修复构建错误

```bash
# 自动修复构建错误
/build-fix
```

**检查清单**：
- [ ] 成功运行 `/tdd` 并完成一个 RED → GREEN → REFACTOR 循环
- [ ] 成功运行 `/code-review` 并理解四级审查
- [ ] 了解了 `/e2e` 端到端测试
- [ ] 了解了 `/build-fix` 构建错误修复

---

## 常见问题

**Q: TDD 不会让开发变慢吗？**

A: 短期看确实多写了测试代码。但长期看：(1) Bug 在开发阶段就被发现，不用等上线后修；(2) 重构时有测试保护，不怕改出新 Bug；(3) 新人加入团队时，测试就是最好的文档。研究表明 TDD 项目的总开发时间比传统开发少 15-35%。

**Q: 覆盖率 80% 是不是太低了？**

A: 对普通业务代码，80% 是投入产出比最好的点。从 80% 提到 100% 的边际成本很高（要覆盖大量极端边界情况），而收益递减。但对安全和财务相关代码，100% 是必须的。

**Q: E2E 测试很慢怎么办？**

A: 正确做法是分层测试：大量快速的单元测试（/tdd）+ 适量的 E2E 测试（/e2e）。E2E 只测核心用户旅程（5-10 个），不测每个按钮。Playwright 支持并行执行，通常 10 个 E2E 测试在 2-3 分钟内完成。

## 下一步

请调用 `AskUserQuestion` 展示以下选项，让学习者点击选择；从每条中提炼 1-5 个词作为 label，其余写入 description，不要要求输入数字：

- 进入下一课：Lesson 23 - 自动化工作流
- 返回主菜单
- 退出学习

---
*阶段 4 | Lesson 22/26 (阶段内 2/3) | 上一课: Lesson 21 - 工程协作概览 | 下一课: Lesson 22.1 - EDD 实战*
