本教程面向已掌握 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
传统 TDD 循环是 Red → Green → Refactor:先写一个失败的测试,写最少代码让测试通过,然后重构。但在实践中,开发者经常遇到三个瓶颈:
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 负责代码生成(怎么测、怎么实现)。
这不是让 Claude 替你写一切。核心纪律是:
| 环节 | 人的职责 | Claude Code 的职责 |
|---|---|---|
| Red | 定义测试场景、边界条件 | 生成测试代码骨架 |
| Green | 确认测试意图正确 | 生成最小实现代码 |
| Refactor | 判断重构方向 | 执行重构、保持测试通过 |
| Review | 审查测试质量 | 检测遗漏场景、建议改进 |
在项目根目录的 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 一个持久的行为约束——它不会跳过测试直接写实现。
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
// 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 的三个阶段分别封装为 Claude Code 自定义 Slash Commands。
/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('应该在错误输入时抛出异常', () => {
// ...
});
});
src/<模块名>.test.ts### 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. 最后运行覆盖率报告
/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. 列出所有重构操作和改进点
# 在 Claude Code 会话中:
# 步骤 1: 描述功能,生成测试(Red)
/tdd-red calculator 四则运算计算器,支持加减乘除,处理除零错误和溢出
# 步骤 2: 让 Claude 写最小实现(Green)
/tdd-green calculator
# 步骤 3: 让 Claude 安全重构(Refactor)
/tdd-refactor calculator
现在用一个完整项目演示整个流程。我们要构建一个数学表达式求值器,支持四则运算、括号和变量。
在 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 尚不存在。
/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 状态)。
/tdd-refactor evaluator
Claude Code 会分析代码并提出重构建议。典型操作包括:
- 提取 TokenType 枚举增强可读性
- 将解析逻辑拆分为独立的 Parser 类
- 添加更精确的错误位置信息
- 使用迭代器模式替代索引传递
每次重构后自动运行测试验证。
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
在 .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 | 写入文件后 | 自动运行关联测试 |
创建 .claude/skills/quality-gate.md:
---
description: 代码质量门禁检查。在代码修改完成后触发,执行完整的质量检查流程。
---
# 质量门禁 Skill
当用户完成代码修改并要求质量检查时,执行以下流程:
## 检查步骤
### 1. 类型检查
```bash
npx tsc --noEmit
如果有错误,列出所有类型错误并建议修复方案。
npx eslint src/ --max-warnings 0
如果有警告或错误,按严重程度排序显示。
npx vitest run --coverage
报告测试结果和覆盖率。如果覆盖率低于阈值,指出未覆盖的行。
检查测试文件是否存在以下问题: - 测试之间有隐式依赖(共享状态) - 测试描述不够具体 - 缺少边界条件测试 - Mock 使用不当
生成结构化质量报告: - ✅ 通过项 - ⚠️ 警告项 - ❌ 失败项 - 📊 覆盖率数据
---
## 第六章:进阶模式——测试生成器与回归防护
### 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 被测模块的内部函数
创建 .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%) ━━━━━━━━━━━━━━━━━━━━
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)
- 存活变异列表及建议的修复测试
- 改进前后的得分对比
创建 .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` 等待
创建 .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`
## 失败处理
任何步骤失败时:
- 显示详细错误信息
- 建议修复命令
- 不继续后续步骤
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
问题:有时 Claude Code 会忽略 CLAUDE.md 中的 TDD 规则,直接写实现代码。
解决方案:在 CLAUDE.md 中增加更强的约束:
## 强制 TDD 约束
- 如果被要求实现一个功能但对应的测试文件不存在,必须先创建测试文件
- 在写实现代码之前,先运行测试确认它们会失败
- 如果用户没有明确要求跳过 TDD,始终遵循 Red-Green-Refactor 流程
问题: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"
}]
}
问题:Claude Code 生成的测试过于简单,缺少边界条件。
解决方案:在 Slash Command 中增加更详细的测试模板:
## 测试场景清单(必须逐项覆盖)
1. ✅ Happy Path — 最简单的正确输入
2. ✅ 边界值 — 最小值、最大值、零、空字符串
3. ✅ 错误输入 — null、undefined、错误类型
4. ✅ 并发/重复 — 多次调用、连续调用
5. ✅ 极端情况 — 超大数据、超深嵌套、Unicode
问题:重构实现代码时测试大面积失败,说明测试过度依赖实现细节。
解决方案:使用 .claude/rules/testing.md 约束:
## 测试设计原则
- 通过公开 API 测试行为,不测试内部实现
- 不断言私有方法的返回值
- 不检查函数调用次数(除非是关键副作用)
- 不依赖代码执行顺序
创建 .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. 示例验证
创建一个简单的示例函数和测试,验证整个流程可用
## 输出
报告已创建的文件列表和验证结果
# 新建项目
mkdir my-tdd-project && cd my-tdd-project
npm init -y
claude init
# 在 Claude Code 会话中
/init-tdd node
| 指标 | 目标值 | 测量方式 |
|---|---|---|
| 测试覆盖率 | ≥ 80% | vitest --coverage |
| Red→Green 时间 | < 5 分钟 | 计时 Claude Code 执行 |
| 重构安全率 | 100% 测试通过 | Hooks 自动验证 |
| 测试/代码比 | 1:1 到 2:1 | 行数统计 |
| 回归捕获率 | > 95% | Mutation Testing 得分 |
创建 .claude/commands/weekly-review.md:
# 周度测试回顾
分析本周测试工作流的效果。
## 执行步骤
1. 运行完整测试套件,记录当前状态
2. 分析覆盖率变化趋势
3. 检查是否有跳过的测试
4. 检查是否有标记为 TODO 的测试
5. 审查最近添加的测试质量
6. 生成改进建议
## 输出报告
- 📊 覆盖率趋势
- ⚠️ 待处理的测试问题
- 💡 改进建议
本教程构建了一个完整的 Claude Code TDD 工作流体系:
核心理念:AI 辅助 TDD 的最大价值不在于让 AI 写测试更快,而在于让人类从"写测试的人"升级为"设计测试策略的人"。你负责思考"测什么",Claude Code 负责"怎么测"。
训练营适用性评估:
| 训练营类型 | 适用性 | 预计时长 | 备注 |
|---|---|---|---|
| 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 等场景全覆盖。
