写测试是开发中最让人拖延的事之一。但没有测试,重构就是在走钢丝。Claude Code 能帮你快速建立测试覆盖,本文从零讲解如何高效用 AI 生成高质量单元测试。
为什么 AI 写测试特别适合?
测试是 AI 编程表现最稳定的任务之一,原因很简单:
- 输入输出明确:函数签名 → 期望行为,有明确的验证标准
- 模式固定:arrange-act-assert 三段式,AI 很擅长
- 边界条件系统化:AI 不会遗漏空值、边界、异常情况
- 无聊工作:人类容易跳过的重复工作,AI 不厌其烦
基础用法:为现有代码补测试
最简单的方式
为 @src/auth/login.ts 的 validatePassword 函数写单元测试,
覆盖正常密码、空密码、过短密码三种情况,
用 Jest + TypeScript,不用 mock
Claude 会:
- 读取函数实现
- 识别边界条件
- 生成对应测试用例
- 在合适位置创建测试文件
要求更高覆盖率
为 @src/services/UserService.ts 写完整测试套件:
- 覆盖所有 public 方法
- 包含正常流程、错误情况、边界值
- 数据库调用用 mock(jest.mock)
- 目标覆盖率 90% 以上
写完后运行测试确认全部通过
关键:"写完后运行测试" — 让 Claude 自己验证,出错自动修复。
测试框架配置示例
Jest(JavaScript / TypeScript)
为 @src/utils/dateParser.ts 写 Jest 测试:
- 使用 describe 分组,每个方法一个 describe 块
- test case 命名用 "should + 预期行为" 格式
- 用 test.each 处理多个相似输入
pytest(Python)
为 @app/services/payment.py 的 ProcessPayment 类写 pytest 测试:
- 用 fixture 处理测试数据和 mock
- 覆盖成功支付、余额不足、网络超时、重复支付四种情况
- 用 monkeypatch 模拟外部 API 调用
JUnit(Java)
为 @src/main/java/com/app/AuthService.java 写 JUnit 5 测试:
- 用 @ParameterizedTest 处理多种输入
- 用 Mockito mock 依赖(UserRepository、PasswordEncoder)
- 测试方法名用 given_when_then 格式
四个高价值测试场景
场景 1:提升现有项目覆盖率
运行测试,查看当前覆盖率报告,
找出覆盖率低于 50% 的模块,
优先为这些模块补写测试
Claude 会:
npm test -- --coverage跑测试- 分析覆盖率报告
- 按优先级补写测试
- 再次运行确认覆盖率提升
场景 2:TDD(测试驱动开发)
在实现功能前先写测试:
我要实现一个购物车 checkout 功能:
- 计算商品总价(含折扣码逻辑)
- 验证库存是否充足
- 生成订单 ID
先按照这个需求写测试用例(会失败),
然后实现功能让测试通过
场景 3:回归测试(发现 Bug 后)
用户报告:当订单金额超过 10000 元时,折扣计算有误。
先写一个复现这个 Bug 的失败测试,
然后找到并修复 Bug,
确认测试通过
这确保这个 Bug 不会再次出现。
场景 4:批量补测试(大型遗留项目)
/batch 为 src/ 目录下所有没有对应测试文件的模块补写测试,
每个文件覆盖率目标 70%,
每个模块独立 PR
内置的 /batch 命令自动分解任务,多代理并行处理,最终每个模块各提一个 PR。
写好"测试 Prompt"的关键
给 Claude 足够的上下文
❌ 太少:
为 UserService 写测试
✅ 充分:
为 @src/services/UserService.ts 写测试:
- 测试框架:Vitest
- 依赖 mock:数据库用 vi.mock,外部 API 用 MSW
- 需要覆盖:createUser(含邮件验证逻辑)、updateProfile、deleteUser
- 用户删除时,所有关联订单应标记为 archived 而非删除
- 写完运行 npm test 确认通过
指定测试风格
测试命名用 given/when/then 风格:
given_userNotExist_when_createUser_then_shouldCreateAndSendEmail
每个测试只断言一件事,不要在一个 test case 里测多个行为
要求处理异步
所有数据库操作都是 async,
测试里正确使用 async/await,
测试网络超时时用 jest.useFakeTimers
在 CLAUDE.md 里固化测试规范
避免每次都重复说明,把测试规范写进 CLAUDE.md:
markdown
# 测试规范
## 框架
- 前端:Vitest + Testing Library
- 后端:Jest + Supertest(集成测试)
## 规范
- 命名:should_[预期结果]_when_[条件]
- 每个 test case 只测一个行为
- 外部依赖(数据库、API)用 mock
- 测试文件放在 __tests__ 目录,与源文件同级
## 目标
- 新功能必须有测试,覆盖率不低于 80%
- Bug 修复必须先写复现测试再修复之后直接说"为 UserService 写测试",Claude 自动按规范来。
常见问题
生成的测试质量不高?
- 提供更多业务上下文
- 说明哪些行为是关键路径
- 要求覆盖具体的边界条件
测试依赖太多 mock,测不到真实逻辑?
尽量减少 mock,只 mock 外部 I/O(数据库、HTTP 请求),
业务逻辑本身不要 mock
测试跑不过?
运行测试看看失败原因,
找到根本问题并修复,
不要只改测试来让它通过(除非测试本身写错了)
来源:Anthropic 官方最佳实践 + 社区测试工程经验