关于 test-quality-analysis
用于分析和改进测试质量的技能,面向审查测试套件的开发者。它涵盖过度模拟、脆弱或不稳定测试、覆盖率缺口及断言问题,并提供 TypeScript、JavaScript 和 Python 的检查命令。
主要功能
- 01识别常见测试异味
- 02分析模拟过多与不稳定测试
- 03检查覆盖率和测试缺口
- 04评估断言与测试隔离
- 05提供 TS、JS 和 Python 检查命令
适用场景
- 01审查测试套件的可维护性
- 02定位造成随机失败的测试
- 03发现关键代码路径的覆盖缺口
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ laurigates/ claude-plugins --skill test-quality-analysis安装后在 Claude Code 中输入/test-quality-analysis确认已加载。
附带文件REFERENCE.md
详细介绍
测试质量分析
用于分析和提升测试质量的专家知识——检测测试异味、过度模拟、覆盖率不足及其他测试反模式。
何时使用此技能
| 在以下情况下使用此技能…… | 在以下情况下改用其他技能…… |
|---|---|
| 审查测试质量和异味 | 编写新的单元测试(使用 vitest-testing) |
| 检测过度模拟或不稳定的测试 | 设置 E2E 测试(使用 playwright-testing) |
| 分析测试覆盖率缺口 | 通过变异测试验证测试(使用 mutation-testing) |
| 提升测试的可维护性 | 生成测试数据(使用 property-based-testing) |
| 审查测试套件中的反模式 | 编写 Python 测试(使用 python-testing) |
核心专长
测试质量维度
- 正确性:测试验证正确的行为
- 可靠性:测试结果具有确定性,不会不稳定
- 可维护性:测试易于理解和修改
- 性能:测试运行速度快
- 覆盖率:测试覆盖关键代码路径
- 隔离性:测试不依赖外部状态
测试异味——速查表
| 异味 | 症状 | 修复方法 |
|---|---|---|
| 过度模拟 | 每个测试中有 3 个以上模拟对象;模拟纯函数 | 仅模拟 I/O 边界;使用真实实现 |
| 脆弱的测试 | 行为未改变,重构却导致测试失败 | 测试公共 API;使用语义化选择器 |
| 不稳定的测试 | 通过或失败不可预测 | 正确使用 async/await;模拟时间;确保隔离性 |
| 测试重复 | 多个测试中复制粘贴设置代码 | 提取到 beforeEach()、测试夹具和辅助函数中 |
| 测试缓慢 | 单元测试套件耗时超过 10 秒 | 对耗时的设置使用 beforeAll();并行运行 |
| 断言不佳 | 使用 toBeDefined()、没有断言、只断言模拟对象 | 使用具体的匹配器;断言输出和状态 |
| 覆盖率不足 | 关键路径未经测试 | 业务逻辑覆盖率达到 80% 以上;测试错误路径和边界 |
分析工具
TypeScript/JavaScript
vitest --coverage # Coverage report
vitest --coverage --coverage.thresholds.lines=80 # Threshold check
vitest --reporter=verbose # Find slow tests
Python
uv run pytest --cov --cov-report=term-missing # Coverage with missing lines
uv run pytest --cov --cov-fail-under=80 # Threshold check
uv run pytest --durations=10 # Find slow tests
关键反模式
测试实现而非行为
// BAD: Testing how
test('uses correct algorithm', () => {
const spy = vi.spyOn(Math, 'sqrt')
calculateDistance({ x: 0, y: 0 }, { x: 3, y: 4 })
expect(spy).toHaveBeenCalled()
})
// GOOD: Testing what
test('calculates distance correctly', () => {
const distance = calculateDistance({ x: 0, y: 0 }, { x: 3, y: 4 })
expect(distance).toBe(5)
})
弱断言
// BAD
expect(users).toBeDefined() // Too vague
expect(mockAPI).toHaveBeenCalled() // Testing mock, not behavior
// GOOD
expect(user).toMatchObject({
id: expect.any(Number),
name: 'John',
email: '[email protected]',
})
覆盖缺失
// BAD: Only tests happy path
test('applies discount', () => {
expect(calculateDiscount(100, 'SAVE20')).toBe(80)
})
// GOOD: Tests all paths
describe('calculateDiscount', () => {
it('applies SAVE20', () => expect(calculateDiscount(100, 'SAVE20')).toBe(80))
it('applies SAVE50', () => expect(calculateDiscount(100, 'SAVE50')).toBe(50))
it('invalid coupon', () => expect(calculateDiscount(100, 'INVALID')).toBe(100))
it('no coupon', () => expect(calculateDiscount(100)).toBe(100))
})
测试结构(AAA 模式)
test('user registration flow', async () => {
// Arrange
const userData = { email: '[email protected]', password: 'secure123' }
const mockEmailService = vi.fn()
// Act
const user = await registerUser(userData, mockEmailService)
// Assert
expect(user).toMatchObject({ email: '[email protected]', emailVerified: false })
expect(mockEmailService).toHaveBeenCalledWith('[email protected]', expect.any(String))
})
Agentic 优化
| 场景 | 命令 |
|---|---|
| 检查覆盖率(TS) | vitest --coverage --reporter=dot |
| 检查覆盖率(Python) | uv run pytest --cov --cov-fail-under=80 -q |
| 查找慢速测试(TS) | vitest --reporter=verbose |
| 查找慢速测试(Python) | uv run pytest --durations=10 -q |
| 缺失代码行(Python) | uv run pytest --cov --cov-report=term-missing |
如需查看详细示例、高级模式和最佳实践,请参阅 REFERENCE.md。
另请参阅
vitest-testing- TypeScript/JavaScript 测试python-testing- Python pytest 测试playwright-testing- E2E 测试mutation-testing- 验证测试有效性
参考资料
评论
支持 Markdown