首页 › tutorials › Claude Code测试驱动与质量门禁实战

Claude Code 测试驱动开发与质量门禁全实战

概述

本教程面向已掌握 Claude Code 基础操作的中级开发者,系统讲解如何将测试驱动开发(TDD)理念与 Claude Code 的 AI 辅助编程深度结合,构建从单测编写到质量门禁的完整自动化体系。学完本教程,你将掌握 Red-Green-Refactor 循环在 AI 时代的最佳实践、Claude Code 原生 TDD Skill 的配置与扩展、Hooks 驱动的质量门禁搭建,以及如何在团队中落地可复用的测试工作流。

适用人群:有 3 个月以上 Claude Code 使用经验、熟悉至少一种测试框架(Jest/Vitest/pytest 等)的开发者。

学习目标: - 理解 AI 辅助 TDD 的核心循环与反模式 - 配置并扩展 Claude Code 内置 TDD Skill - 用 Hooks 构建多层质量门禁 - 完成一个可运行的 TDD 实战项目


前置条件

工具/知识 最低要求
Claude Code ≥ 1.0.18(支持 Skills 和 Hooks)
Node.js ≥ 18.x(本教程使用 Vitest)
Git ≥ 2.30
测试框架基础 了解 describe/it/expect 模式
Claude Code 基础 会使用 /init、/compact、CLAUDE.md

环境准备:

# 创建项目目录
mkdir tdd-with-claude && cd tdd-with-claude

# 初始化 Node 项目
npm init -y

# 安装 Vitest
npm install -D vitest

# 初始化 Claude Code 配置
claude init

# 验证 Claude Code 版本
claude --version

第一章:AI 时代的 TDD——为什么传统模式需要升级

1.1 传统 TDD 的痛点

传统 TDD 循环是 Red → Green → Refactor:先写一个失败的测试,写最少代码让测试通过,然后重构。但在实践中,开发者经常遇到三个瓶颈:

1.2 Claude Code 如何改变游戏规则

Claude Code 不是替代 TDD,而是加速 TDD 每个环节:

flowchart LR
    subgraph 传统TDD
        T1[手写测试] --> T2[手写实现] --> T3[手动重构]
    end
    subgraph AI辅助TDD
        A1["描述测试意图<br/>Claude生成测试代码"] --> A2["Claude快速实现<br/>最小可行代码"] --> A3["Claude识别异味<br/>建议安全重构"]
    end
    传统TDD -.->|耗时比 3:1:2| AI辅助TDD
    style AI辅助TDD fill:#e8f5e9

关键区别:在 AI 辅助 TDD 中,你的角色从"写代码的人"变成"设计测试的人"。你定义测试意图(测试什么、边界在哪),Claude Code 负责代码生成(怎么测、怎么实现)。

1.3 核心原则:人定意图,AI 定实现

这不是让 Claude 替你写一切。核心纪律是:

环节 人的职责 Claude Code 的职责
Red 定义测试场景、边界条件 生成测试代码骨架
Green 确认测试意图正确 生成最小实现代码
Refactor 判断重构方向 执行重构、保持测试通过
Review 审查测试质量 检测遗漏场景、建议改进

第二章:项目配置——为 TDD 打造 Claude Code 环境

2.1 CLAUDE.md 中的 TDD 指令

在项目根目录的 CLAUDE.md 中添加 TDD 工作规范:

# TDD 工作规范

## 开发纪律
- 所有新功能必须先写测试,再写实现(Red-Green-Refactor)
- 测试文件放在 `src/` 同级目录,命名为 `*.test.ts`
- 使用 Vitest 作为测试框架
- 每次修改代码后必须运行相关测试验证

## 测试要求
- 每个公开函数至少 3 个测试:正常路径、边界条件、错误处理
- 测试描述使用中文,说明测试意图
- 使用 `describe` 按功能分组,`it` 描述具体场景
- Mock 外部依赖,不 Mock 被测模块内部函数

## 质量标准
- 测试覆盖率不低于 80%
- 所有测试必须在 10 秒内完成
- 禁止使用 `any` 类型

为什么要在 CLAUDE.md 写这些? 因为 Claude Code 每次启动会话时自动读取这个文件。把 TDD 纪律写在这里,等于给 Claude Code 一个持久的行为约束——它不会跳过测试直接写实现。

2.2 项目结构设计

tdd-with-claude/
├── .claude/
│   ├── commands/          # 自定义 Slash Commands
│   │   ├── tdd-red.md     # TDD Red 阶段命令
│   │   ├── tdd-green.md   # TDD Green 阶段命令
│   │   └── tdd-refactor.md # TDD Refactor 阶段命令
│   ├── rules/             # 项目规则
│   │   └── testing.md     # 测试规则详情
│   ├── settings.json      # Hooks 和权限配置
│   └── skills/            # 自定义 Skills
├── src/
│   ├── calculator.ts
│   ├── calculator.test.ts
│   ├── validator.ts
│   └── validator.test.ts
├── CLAUDE.md
├── vitest.config.ts
└── package.json

2.3 Vitest 配置

// vitest.config.ts
import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    globals: true,
    coverage: {
      provider: 'v8',
      reporter: ['text', 'html', 'json-summary'],
      include: ['src/**/*.ts'],
      exclude: ['src/**/*.test.ts'],
      thresholds: {
        lines: 80,
        functions: 80,
        branches: 75,
        statements: 80,
      },
    },
    testTimeout: 10000,
    hookTimeout: 10000,
  },
});

第三章:三个 TDD Slash Commands——让纪律成为命令

这是本教程的核心创新:将 TDD 的三个阶段分别封装为 Claude Code 自定义 Slash Commands。

3.1 /tdd-red:生成测试命令

创建 .claude/commands/tdd-red.md:

# TDD Red Phase - 测试先行

你正在执行 TDD 的 Red 阶段。根据以下规则生成测试:

## 输入
用户会描述要测试的功能。参数: $ARGUMENTS

## 你的任务
1. 分析功能需求,识别所有测试场景
2. 为每个场景生成一个测试用例
3. 确保覆盖:正常路径、边界条件、错误处理
4. **不要**生成任何实现代码,只生成测试

## 测试模板
```typescript
import { describe, it, expect } from 'vitest';

describe('功能名称', () => {
  it('应该在正常输入时返回预期结果', () => {
    // Arrange - 准备测试数据
    // Act - 执行被测函数
    // Assert - 验证结果
  });

  it('应该在边界条件时正确处理', () => {
    // ...
  });

  it('应该在错误输入时抛出异常', () => {
    // ...
  });
});

输出要求

### 3.2 `/tdd-green`:最小实现命令

创建 `.claude/commands/tdd-green.md`:

```markdown
# TDD Green Phase - 最小实现

你正在执行 TDD 的 Green 阶段。

## 输入
参数: $ARGUMENTS(要实现的模块名)

## 你的任务
1. 读取对应的测试文件 `src/$ARGUMENTS.test.ts`
2. 分析所有失败的测试用例
3. 编写**最少**的代码让所有测试通过
4. 不要过度设计,不要添加测试未要求的功能

## 纪律要求
- 只写让测试通过的最少代码
- 允许硬编码值(Refactor 阶段再优化)
- 不要添加额外的错误处理(除非测试要求)
- 不要添加日志、注释等非必要代码

## 验证步骤
1. 写完实现后立即运行 `npx vitest run src/$ARGUMENTS.test.ts`
2. 如果测试全部通过,报告 Green 状态
3. 如果有测试失败,修改实现直到全部通过
4. 最后运行覆盖率报告

3.3 /tdd-refactor:安全重构命令

创建 .claude/commands/tdd-refactor.md:

# TDD Refactor Phase - 安全重构

你正在执行 TDD 的 Refactor 阶段。

## 输入
参数: $ARGUMENTS(要重构的模块名)

## 你的任务
1. 读取 `src/$ARGUMENTS.ts` 和 `src/$ARGUMENTS.test.ts`
2. 识别代码异味和改进机会:
   - 重复代码
   - 过长的函数
   - 命名不清晰
   - 可以简化的逻辑
   - 缺少类型安全
3. 执行重构,**保持所有测试通过**

## 重构纪律
- 每次只做一种重构
- 每次重构后都运行测试
- 如果测试失败,立即回滚
- 不改变公开 API

## 验证步骤
1. 重构前运行测试,记录基线
2. 执行重构
3. 重构后运行测试,确认全部通过
4. 运行覆盖率报告,确认未降低
5. 列出所有重构操作和改进点

3.4 使用方式

# 在 Claude Code 会话中:

# 步骤 1: 描述功能,生成测试(Red)
/tdd-red calculator 四则运算计算器,支持加减乘除,处理除零错误和溢出

# 步骤 2: 让 Claude 写最小实现(Green)
/tdd-green calculator

# 步骤 3: 让 Claude 安全重构(Refactor)
/tdd-refactor calculator

第四章:实战项目——用 TDD 构建表达式求值器

现在用一个完整项目演示整个流程。我们要构建一个数学表达式求值器,支持四则运算、括号和变量。

4.1 Red 阶段:定义测试

在 Claude Code 中输入:

/tdd-red evaluator 数学表达式求值器:
1. 支持加减乘除四则运算
2. 支持括号改变优先级
3. 支持变量赋值和使用(x = 5, x + 3)
4. 除零时抛出 DivisionByZeroError
5. 非法表达式时抛出 SyntaxError

Claude Code 会生成类似以下测试:

// src/evaluator.test.ts
import { describe, it, expect } from 'vitest';
import { evaluate, Evaluator } from './evaluator';

describe('表达式求值器', () => {
  describe('基本四则运算', () => {
    it('应该正确计算加法', () => {
      expect(evaluate('2 + 3')).toBe(5);
    });

    it('应该正确计算减法', () => {
      expect(evaluate('10 - 4')).toBe(6);
    });

    it('应该正确计算乘法', () => {
      expect(evaluate('3 * 7')).toBe(21);
    });

    it('应该正确计算除法', () => {
      expect(evaluate('15 / 3')).toBe(5);
    });

    it('应该正确处理运算优先级', () => {
      expect(evaluate('2 + 3 * 4')).toBe(14);
    });

    it('应该正确处理浮点数', () => {
      expect(evaluate('1.5 + 2.5')).toBe(4);
    });
  });

  describe('括号支持', () => {
    it('应该用括号改变优先级', () => {
      expect(evaluate('(2 + 3) * 4')).toBe(20);
    });

    it('应该支持嵌套括号', () => {
      expect(evaluate('((1 + 2) * (3 + 4))')).toBe(21);
    });

    it('应该检测不匹配的括号', () => {
      expect(() => evaluate('(2 + 3')).toThrow(SyntaxError);
    });
  });

  describe('变量支持', () => {
    it('应该支持变量赋值和使用', () => {
      const ev = new Evaluator();
      ev.setVariable('x', 5);
      expect(ev.evaluate('x + 3')).toBe(8);
    });

    it('应该在使用未定义变量时抛出错误', () => {
      const ev = new Evaluator();
      expect(() => ev.evaluate('y + 1')).toThrow();
    });
  });

  describe('错误处理', () => {
    it('应该在除零时抛出 DivisionByZeroError', () => {
      expect(() => evaluate('10 / 0')).toThrow();
    });

    it('应该在非法表达式时抛出 SyntaxError', () => {
      expect(() => evaluate('2 + + 3')).toThrow(SyntaxError);
    });

    it('应该在空输入时抛出 SyntaxError', () => {
      expect(() => evaluate('')).toThrow(SyntaxError);
    });
  });
});

运行测试确认全部失败:

npx vitest run src/evaluator.test.ts

预期结果:所有测试失败(Red 状态),因为 evaluator.ts 尚不存在。

4.2 Green 阶段:最小实现

/tdd-green evaluator

Claude Code 会生成最小实现:

// src/evaluator.ts
export class DivisionByZeroError extends Error {
  constructor() {
    super('Division by zero');
    this.name = 'DivisionByZeroError';
  }
}

export class Evaluator {
  private variables: Map<string, number> = new Map();

  setVariable(name: string, value: number): void {
    this.variables.set(name, value);
  }

  evaluate(expression: string): number {
    if (!expression.trim()) {
      throw new SyntaxError('Empty expression');
    }
    // 替换变量
    let expr = expression;
    for (const [name, value] of this.variables) {
      expr = expr.replace(new RegExp(`\\b${name}\\b`, 'g'), String(value));
    }
    // 检测未定义变量(裸字母)
    if (/[a-zA-Z_]\w*/g.test(expr.replace(/\b(sin|cos|tan|log)\b/g, ''))) {
      const remaining = expr.match(/\b[a-zA-Z_]\w*\b/g);
      if (remaining) {
        throw new Error(`Undefined variable: ${remaining[0]}`);
      }
    }
    return this.parseExpression(expr);
  }

  private parseExpression(expr: string): number {
    try {
      // 安全的数学表达式解析
      const tokens = this.tokenize(expr);
      const result = this.parseAddSub(tokens, 0);
      if (tokens[result.index] !== undefined) {
        throw new SyntaxError(`Unexpected token: ${tokens[result.index]}`);
      }
      return result.value;
    } catch (e) {
      if (e instanceof DivisionByZeroError || e instanceof SyntaxError) throw e;
      throw new SyntaxError(`Invalid expression: ${expr}`);
    }
  }

  private tokenize(expr: string): string[] {
    return expr.match(/(\d+\.?\d*|[+\-*/()])/g) || [];
  }

  private parseAddSub(tokens: string[], pos: number): { value: number; index: number } {
    let left = this.parseMulDiv(tokens, pos);
    while (tokens[left.index] === '+' || tokens[left.index] === '-') {
      const op = tokens[left.index];
      const right = this.parseMulDiv(tokens, left.index + 1);
      left = {
        value: op === '+' ? left.value + right.value : left.value - right.value,
        index: right.index,
      };
    }
    return left;
  }

  private parseMulDiv(tokens: string[], pos: number): { value: number; index: number } {
    let left = this.parsePrimary(tokens, pos);
    while (tokens[left.index] === '*' || tokens[left.index] === '/') {
      const op = tokens[left.index];
      const right = this.parsePrimary(tokens, left.index + 1);
      if (op === '/' && right.value === 0) throw new DivisionByZeroError();
      left = {
        value: op === '*' ? left.value * right.value : left.value / right.value,
        index: right.index,
      };
    }
    return left;
  }

  private parsePrimary(tokens: string[], pos: number): { value: number; index: number } {
    if (tokens[pos] === '(') {
      const result = this.parseAddSub(tokens, pos + 1);
      if (tokens[result.index] !== ')') {
        throw new SyntaxError('Mismatched parentheses');
      }
      return { value: result.value, index: result.index + 1 };
    }
    const num = parseFloat(tokens[pos]);
    if (isNaN(num)) {
      throw new SyntaxError(`Unexpected token: ${tokens[pos]}`);
    }
    return { value: num, index: pos + 1 };
  }
}

export function evaluate(expression: string): number {
  return new Evaluator().evaluate(expression);
}

运行测试:

npx vitest run src/evaluator.test.ts

预期结果:所有测试通过(Green 状态)。

4.3 Refactor 阶段:安全重构

/tdd-refactor evaluator

Claude Code 会分析代码并提出重构建议。典型操作包括: - 提取 TokenType 枚举增强可读性 - 将解析逻辑拆分为独立的 Parser 类 - 添加更精确的错误位置信息 - 使用迭代器模式替代索引传递

每次重构后自动运行测试验证。


第五章:Hooks 驱动的质量门禁

5.1 质量门禁架构

flowchart TB
    subgraph 质量门禁层
        direction TB
        L1["第一层:PreToolUse<br/>写文件前自动格式化"]
        L2["第二层:PostToolUse<br/>修改代码后自动检查"]
        L3["第三层:Notification<br/>测试失败时告警"]
    end

    Dev[开发者操作] --> L1
    L1 --> L2
    L2 --> L3
    L3 --> Pass{通过?}
    Pass -->|是| OK[代码就绪]
    Pass -->|否| Fix[显示修复建议]

    style L1 fill:#fff3e0
    style L2 fill:#e3f2fd
    style L3 fill:#fce4ec

5.2 配置 Hooks

在 .claude/settings.json 中配置质量门禁 Hooks:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "npx prettier --write \"$CLAUDE_FILE_PATH\" 2>/dev/null || true"
          }
        ]
      },
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "FILE=\"$CLAUDE_FILE_PATH\"; if [[ \"$FILE\" == src/*.ts && \"$FILE\" != *.test.ts && \"$FILE\" != *.d.ts ]]; then TEST_FILE=\"${FILE%.ts}.test.ts\"; if [ -f \"$TEST_FILE\" ]; then npx vitest run \"$TEST_FILE\" --reporter=verbose 2>&1 | tail -20; fi; fi"
          }
        ]
      }
    ],
    "PreToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "FILE=\"$CLAUDE_FILE_PATH\"; if [[ \"$FILE\" == *.ts && \"$FILE\" != *.test.ts ]]; then npx tsc --noEmit \"$FILE\" 2>&1 | head -10; fi"
          }
        ]
      }
    ]
  }
}

三道门禁解析:

层级 Hook 类型 触发时机 作用
第一层 PreToolUse 写入文件前 TypeScript 类型检查,阻止类型错误
第二层 PostToolUse #1 写入文件后 Prettier 自动格式化
第三层 PostToolUse #2 写入文件后 自动运行关联测试

5.3 自定义质量门禁 Skill

创建 .claude/skills/quality-gate.md:

---
description: 代码质量门禁检查。在代码修改完成后触发,执行完整的质量检查流程。
---

# 质量门禁 Skill

当用户完成代码修改并要求质量检查时,执行以下流程:

## 检查步骤

### 1. 类型检查
```bash
npx tsc --noEmit

如果有错误,列出所有类型错误并建议修复方案。

2. Lint 检查

npx eslint src/ --max-warnings 0

如果有警告或错误,按严重程度排序显示。

3. 测试执行

npx vitest run --coverage

报告测试结果和覆盖率。如果覆盖率低于阈值,指出未覆盖的行。

4. 测试质量审计

检查测试文件是否存在以下问题: - 测试之间有隐式依赖(共享状态) - 测试描述不够具体 - 缺少边界条件测试 - Mock 使用不当

5. 输出报告

生成结构化质量报告: - ✅ 通过项 - ⚠️ 警告项 - ❌ 失败项 - 📊 覆盖率数据

---

## 第六章:进阶模式——测试生成器与回归防护

### 6.1 批量测试生成命令

创建 `.claude/commands/gen-tests.md`:

```markdown
# 批量测试生成器

为指定目录下所有源文件生成测试。

## 输入
参数: $ARGUMENTS(源文件目录,默认 src/)

## 你的任务
1. 扫描目录下的所有 `.ts` 文件(排除 `.test.ts` 和 `.d.ts`)
2. 对每个文件:
   a. 分析导出的函数/类
   b. 生成测试文件 `*.test.ts`
   c. 确保测试文件可执行
3. 运行所有生成的测试
4. 报告每个文件的测试数量和通过率

## 测试生成规则
- 每个纯函数至少 5 个测试:2 正常 + 2 边界 + 1 错误
- 每个类的方法至少 3 个测试
- 使用 AAA 模式(Arrange-Act-Assert)
- 不 Mock 被测模块的内部函数

6.2 回归测试守护命令

创建 .claude/commands/regression-guard.md:

# 回归测试守护

在修改代码前快照当前测试状态,修改后对比。

## 输入
参数: $ARGUMENTS(要修改的模块名)

## 你的任务
1. 运行当前所有测试,记录基线结果
2. 用户进行代码修改
3. 修改完成后再次运行所有测试
4. 对比前后结果,报告:
   - 新增的通过测试
   - 新增的失败测试(回归)
   - 新增的跳过测试
   - 性能变化(执行时间对比)

## 回归报告格式

📊 回归测试报告 ━━━━━━━━━━━━━━━━━━━━ 基线: 42 passed, 0 failed 当前: 44 passed, 1 failed ━━━━━━━━━━━━━━━━━━━━ ✅ 新增通过: 2 tests ❌ 回归: 1 test - src/calculator.test.ts > 除法 > 应该处理大数溢出 ⏱️ 性能: +120ms (+15%) ━━━━━━━━━━━━━━━━━━━━


6.3 Mutation Testing 集成

Mutation Testing 是验证测试质量的终极武器——通过故意引入 Bug,检查测试是否能捕获。

# 安装 Stryker(JavaScript/TypeScript 的 Mutation Testing 框架)
npm install -D @stryker-mutator/core @stryker-mutator/vitest-runner

创建 .claude/commands/mutation-test.md:

# Mutation Testing - 变异测试

验证测试质量,检查测试能否捕获故意引入的 Bug。

## 输入
参数: $ARGUMENTS(要变异测试的模块名)

## 你的任务
1. 安排 Stryker 配置(如未配置)
2. 对目标模块运行变异测试
3. 分析变异存活者(Survived Mutants)
4. 为每个存活变异生成补充测试
5. 重新运行变异测试验证改进效果

## 输出格式
- 变异得分(Mutation Score)
- 存活变异列表及建议的修复测试
- 改进前后的得分对比

第七章:团队级工作流——从个人到团队

7.1 共享测试规则

创建 .claude/rules/testing.md:

# 测试规则

## 命名规范
- 测试文件:`<module>.test.ts`
- 测试描述:`describe` 用功能名,`it` 用中文描述场景
- 工具函数:`test-utils.ts` 或 `helpers/test-*.ts`

## 覆盖率要求
- 核心业务逻辑:≥ 90%
- 工具函数:≥ 80%
- UI 组件:≥ 60%(重点测交互逻辑)

## Mock 策略
- Mock 外部 API 调用
- Mock 文件系统和时间相关函数
- **禁止** Mock 被测模块自身的函数
- Mock 数据放在 `__mocks__/` 目录

## 禁止事项
- 禁止 `ts-ignore` / `@ts-ignore`
- 禁止使用 `as any`
- 禁止跳过测试(`xit` / `skip`)除非标注原因和 issue 号
- 禁止在测试中使用 `setTimeout` 等待

7.2 CI 集成脚本

创建 .claude/commands/ci-check.md:

# CI 质量检查

模拟 CI 环境执行完整质量检查。

## 执行步骤
1. **安装依赖**: `npm ci`
2. **类型检查**: `npx tsc --noEmit`
3. **Lint**: `npx eslint src/ --max-warnings 0`
4. **单元测试**: `npx vitest run --coverage`
5. **覆盖率阈值**: 检查是否达到 80%
6. **构建验证**: `npm run build`

## 失败处理
任何步骤失败时:
- 显示详细错误信息
- 建议修复命令
- 不继续后续步骤

7.3 工作流全景图

flowchart TB
    subgraph 开发阶段
        A["开发者输入需求"] --> B["/tdd-red<br/>生成测试"]
        B --> C{"所有测试<br/>失败?"}
        C -->|是| D["/tdd-green<br/>最小实现"]
        C -->|否| B
        D --> E{"所有测试<br/>通过?"}
        E -->|是| F["/tdd-refactor<br/>安全重构"]
        E -->|否| D
        F --> G{"测试仍<br/>通过?"}
        G -->|是| H["/quality-gate<br/>质量门禁"]
        G -->|否| F
    end

    subgraph 质量门禁
        H --> I["类型检查"]
        I --> J["Lint 检查"]
        J --> K["测试 + 覆盖率"]
        K --> L["测试质量审计"]
    end

    subgraph 持续保障
        L --> M["提交代码"]
        M --> N["CI 自动执行"]
        N --> O["回归测试守护"]
    end

    style B fill:#ffcdd2
    style D fill:#c8e6c9
    style F fill:#bbdefb
    style H fill:#fff9c4

第八章:常见问题与解决方案

8.1 Claude Code 跳过测试直接写实现

问题:有时 Claude Code 会忽略 CLAUDE.md 中的 TDD 规则,直接写实现代码。

解决方案:在 CLAUDE.md 中增加更强的约束:

## 强制 TDD 约束
- 如果被要求实现一个功能但对应的测试文件不存在,必须先创建测试文件
- 在写实现代码之前,先运行测试确认它们会失败
- 如果用户没有明确要求跳过 TDD,始终遵循 Red-Green-Refactor 流程

8.2 Hooks 执行缓慢影响体验

问题:PostToolUse Hook 每次编辑都运行测试,对于大型项目会很慢。

解决方案:优化 Hook 只运行受影响的测试:

{
  "matcher": "Write|Edit",
  "hooks": [{
    "type": "command",
    "command": "FILE=\"$CLAUDE_FILE_PATH\"; if [[ \"$FILE\" == src/*.ts ]]; then TEST=\"${FILE%.ts}.test.ts\"; [ -f \"$TEST\" ] && npx vitest run \"$TEST\" --reporter=basic 2>&1 | tail -5; fi"
  }]
}

8.3 生成的测试质量不够高

问题:Claude Code 生成的测试过于简单,缺少边界条件。

解决方案:在 Slash Command 中增加更详细的测试模板:

## 测试场景清单(必须逐项覆盖)
1. ✅ Happy Path — 最简单的正确输入
2. ✅ 边界值 — 最小值、最大值、零、空字符串
3. ✅ 错误输入 — null、undefined、错误类型
4. ✅ 并发/重复 — 多次调用、连续调用
5. ✅ 极端情况 — 超大数据、超深嵌套、Unicode

8.4 测试与实现之间的耦合过紧

问题:重构实现代码时测试大面积失败,说明测试过度依赖实现细节。

解决方案:使用 .claude/rules/testing.md 约束:

## 测试设计原则
- 通过公开 API 测试行为,不测试内部实现
- 不断言私有方法的返回值
- 不检查函数调用次数(除非是关键副作用)
- 不依赖代码执行顺序

第九章:项目模板——一键初始化 TDD 项目

9.1 一键初始化命令

创建 .claude/commands/init-tdd.md:

# TDD 项目初始化器

为当前项目配置完整的 TDD 工作流。

## 输入
参数: $ARGUMENTS(项目类型:node / react / api,默认 node)

## 执行步骤

### 1. 项目结构
创建以下目录和文件:
- `src/` — 源代码
- `src/*.test.ts` — 测试文件
- `.claude/commands/` — TDD 命令
- `.claude/rules/testing.md` — 测试规则
- `.claude/skills/quality-gate.md` — 质量门禁

### 2. 依赖安装
根据项目类型安装测试框架:
- node: `npm install -D vitest`
- react: `npm install -D vitest @testing-library/react jsdom`
- api: `npm install -D vitest supertest`

### 3. 配置文件
- 生成 `vitest.config.ts`
- 更新 `package.json` scripts
- 配置 `.claude/settings.json` Hooks

### 4. CLAUDE.md 模板
生成包含 TDD 规范的 CLAUDE.md

### 5. 示例验证
创建一个简单的示例函数和测试,验证整个流程可用

## 输出
报告已创建的文件列表和验证结果

9.2 使用模板启动新项目

# 新建项目
mkdir my-tdd-project && cd my-tdd-project
npm init -y
claude init

# 在 Claude Code 会话中
/init-tdd node

第十章:效果度量与持续改进

10.1 关键指标

指标 目标值 测量方式
测试覆盖率 ≥ 80% vitest --coverage
Red→Green 时间 < 5 分钟 计时 Claude Code 执行
重构安全率 100% 测试通过 Hooks 自动验证
测试/代码比 1:1 到 2:1 行数统计
回归捕获率 > 95% Mutation Testing 得分

10.2 周度回顾命令

创建 .claude/commands/weekly-review.md:

# 周度测试回顾

分析本周测试工作流的效果。

## 执行步骤
1. 运行完整测试套件,记录当前状态
2. 分析覆盖率变化趋势
3. 检查是否有跳过的测试
4. 检查是否有标记为 TODO 的测试
5. 审查最近添加的测试质量
6. 生成改进建议

## 输出报告
- 📊 覆盖率趋势
- ⚠️ 待处理的测试问题
- 💡 改进建议

总结

本教程构建了一个完整的 Claude Code TDD 工作流体系:

  1. 纪律层:通过 CLAUDE.md 和 Rules 强制 TDD 规范
  2. 命令层:通过 Slash Commands 封装 Red/Green/Refactor 三阶段
  3. 门禁层:通过 Hooks 自动运行类型检查、格式化和测试
  4. 质量层:通过质量门禁 Skill 做全面审计
  5. 守护层:通过回归守护和 Mutation Testing 持续保障

核心理念:AI 辅助 TDD 的最大价值不在于让 AI 写测试更快,而在于让人类从"写测试的人"升级为"设计测试策略的人"。你负责思考"测什么",Claude Code 负责"怎么测"。


参考来源

  1. Extend Claude with skills — Claude Code Official Docs — Anthropic 官方 Skills 文档,涵盖自定义命令和 Skill 创建
  2. Best practices for Claude Code — Claude Code Official Docs — 官方最佳实践,包含上下文管理和工作流建议
  3. TDD with Claude — Claude Code Ultimate Guide — 社区验证的 Claude Code TDD 工作流
  4. Claude Code Skills Tutorial: Custom Slash Commands and Automations — 完整的 Slash Commands 创建教程
  5. Git Hooks with Claude Code: Quality Gates with Husky — Hooks 驱动的质量门禁实战

训练营适用性评估:

训练营类型 适用性 预计时长 备注
AI 辅助开发中级营 ⭐⭐⭐⭐⭐ 4 小时 完美匹配,需前置 Claude Code 基础
企业工程效能训练营 ⭐⭐⭐⭐ 3 小时 侧重 Hooks 和质量门禁部分
全栈开发实战营 ⭐⭐⭐ 6 小时 需结合具体项目框架扩展
TDD 专项训练营 ⭐⭐⭐⭐ 5 小时 AI 辅助视角的 TDD 教学创新
团队规范化工作坊 ⭐⭐⭐⭐ 3 小时 侧重团队命令库和规则体系

[!tip] 51学通信知识星球 星主:爱卫生(微信:gprshome201101)——公众号「51学通信」创办者,19 年通信行业运维与讲师经验,著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书(各大电商平台有售)。 星球定位:深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域,主打运维岗位与信令分析。 当前规模:5200 篇主题 / 990 个回答,198 元/年。 加入福利:加入星球后请加爱卫生微信,拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题,另有群内分享。 AI 加持:51学通信知识星球已作为 skill 接入 WorkBuddy,使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例,做总结、找文档和 PPT 等场景全覆盖。

51学通信知识星球海报-扫码加入