很多项目测试覆盖率长期停留在 30% 左右——写测试太费时间。 Claude Code 能把补测试的效率提升 5 倍,让你快速达到健康的覆盖率水平。
第一步:读懂覆盖率报告,找到高价值盲区
bash
# JavaScript/TypeScript(Jest)
npx jest --coverage --coverageReporters=text-summary,html
# Python(pytest)
pytest --cov=src --cov-report=html --cov-report=term-missing
# 生成报告后,打开 coverage/index.html 查看优先补测试的顺序:
优先级 1:0% 覆盖的核心业务逻辑(services/、utils/)
优先级 2:分支覆盖率低的复杂函数(有多个 if/else 分支)
优先级 3:错误处理路径(catch 块、404/500 分支)
跳过:纯配置文件、自动生成代码、测试本身
针对未覆盖行生成测试
把覆盖率报告直接给 Claude,让它精准补测试:
你:这是 Istanbul 的覆盖率报告(未覆盖行标注 E/I/B):
src/services/pricing.service.ts
Statements: 62% (31/50)
Branches: 45% (9/20)
Lines未覆盖: 34, 35, 42-48, 67, 71-80
第 34-35 行:折扣计算的 VIP 用户分支
第 42-48 行:库存不足时的降级策略
第 71-80 行:并发超卖的乐观锁重试逻辑
请专门为这些未覆盖的行补充测试,
测试名称要清楚描述触发条件。
Claude:生成针对这些具体行的测试,确保每行都被执行到
让 Claude 自动发现边界条件
你:分析 calculateShippingFee(weight, distance, isExpress) 函数,
找出所有需要测试的边界条件和特殊情况,
然后为每个边界条件生成一个测试用例。
Claude:
识别出以下需要测试的场景:
数值边界:
- weight = 0(最小值)
- weight = 0.001(最小正数)
- weight = 30(标准上限,超出需要大件处理费)
- distance = 0(同城)
- distance = 2000(超出配送范围)
组合情况:
- 重货 + 远距离 + 急件(费用叠加验证)
- 轻货 + 同城 + 普通(基础费用)
错误输入:
- weight = -1(负数)
- weight = NaN
- distance = null
业务规则:
- VIP 用户折扣是否正确叠加
- 促销期间免运费条件
[为每个场景生成测试代码]
Mock 复杂依赖
Mock 数据库(Jest)
typescript
// 不要真实调用 DB,用 jest.mock
import { PrismaClient } from '@prisma/client';
import { mockDeep, DeepMockProxy } from 'jest-mock-extended';
jest.mock('../db', () => ({
__esModule: true,
default: mockDeep<PrismaClient>(),
}));
import db from '../db';
const mockDb = db as DeepMockProxy<PrismaClient>;
test('创建用户成功', async () => {
mockDb.user.create.mockResolvedValue({
id: 'user-001',
email: 'test@example.com',
name: 'Test User',
createdAt: new Date(),
});
const result = await createUser({ email: 'test@example.com', name: 'Test User' });
expect(result.id).toBe('user-001');
expect(mockDb.user.create).toHaveBeenCalledWith({
data: { email: 'test@example.com', name: 'Test User' }
});
});Mock 时间(避免时间相关的不稳定测试)
typescript
// 用 jest.useFakeTimers 控制时间
test('Token 过期后应该返回 401', () => {
jest.useFakeTimers();
jest.setSystemTime(new Date('2026-01-01'));
const token = generateToken({ userId: '123', expiresIn: '1h' });
// 推进时间超过 1 小时
jest.advanceTimersByTime(2 * 60 * 60 * 1000);
expect(() => verifyToken(token)).toThrow('Token expired');
jest.useRealTimers();
});Mock HTTP 请求(Python)
python
from unittest.mock import patch, MagicMock
import pytest
from services.payment import charge_card
@patch('services.payment.stripe.PaymentIntent.create')
def test_charge_card_success(mock_stripe):
mock_stripe.return_value = MagicMock(
id='pi_test_123',
status='succeeded',
amount=5000
)
result = charge_card(amount=5000, card_token='tok_test')
assert result.success is True
assert result.payment_id == 'pi_test_123'
mock_stripe.assert_called_once_with(amount=5000, currency='cny',
payment_method=card_token)CI 覆盖率门禁
yaml
# .github/workflows/test.yml
- name: Run tests with coverage
run: npx jest --coverage --coverageThreshold='{"global":{"lines":80}}'
# 覆盖率低于 80% 时 CI 失败,阻止合并
# 或者更精细的控制
- name: Check coverage
run: |
COVERAGE=$(npx jest --coverage --json 2>/dev/null | python3 -c "import json,sys; d=json.load(sys.stdin); print(d['coverageMap']['total']['lines']['pct'])")
echo "当前覆盖率:$COVERAGE%"
if (( $(echo "$COVERAGE < 75" | bc -l) )); then
echo "覆盖率低于 75%,请补充测试后再合并"
exit 1
fi测试质量 vs 数量
高覆盖率不等于高质量测试。让 Claude 帮你审查测试质量:
你:我的覆盖率已经 85% 了,但 Code Review 发现很多测试只是
简单调用函数而不做有意义的断言。
帮我审查这些测试,找出:
1. 没有实际断言的测试(或只断言 toBeTruthy)
2. 测试名称和测试内容不匹配的
3. 没有测试失败路径的函数
Claude:发现以下测试质量问题:
低质量测试(建议重写):
1. it('should work') → 只有 expect(fn()).toBeTruthy(),无法捕获具体错误
2. test('handles error') → 没有测试错误情况,只测了成功路径
缺少失败路径测试的函数:
- parseJson():缺少无效 JSON 输入测试
- fetchUser():缺少网络超时和 404 测试
来源:Claude Code 官方文档 - docs.anthropic.com/en/docs/claude-code