关于 testing-anti-patterns
面向编写、修改或审查测试的开发者,强调验证真实代码行为而非模拟对象,并提供避免模拟不完整、生产代码加入测试专用方法等问题的指导。
主要功能
- 01验证真实行为而非模拟对象
- 02避免生产代码出现测试专用方法
- 03理解依赖后再模拟
- 04保持模拟对象完整
- 05用 TDD 预防常见问题
适用场景
- 01审查断言模拟调用的测试
- 02判断依赖是否需要模拟
- 03发现不完整的模拟数据
- 04避免把测试留到实现之后
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ bobmatnyc/ claude-mpm-skills --skill testing-anti-patterns安装后在 Claude Code 中输入/testing-anti-patterns确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
metadata.jsonreferences/completeness-anti-patterns.mdcore-anti-patterns.mddetection-guide.mdpython-examples.mdtdd-connection.md详细介绍
测试反模式
概述
测试必须验证真实行为,而不是模拟行为。模拟是用于隔离的手段,不是测试对象。
核心原则: 测试代码的行为,而不是模拟的行为。
遵循严格的 TDD 可避免这些反模式。 完整的 TDD 工作流请参见测试驱动开发技能(可在技能库中找到)。
何时使用此技能
在以下情况下启用此技能:
- 编写或修改测试 - 验证测试是否覆盖真实行为
- 添加模拟 - 确保模拟是必要且正确的
- 检查测试失败 - 检查问题是否出在模拟行为上
- 想要添加仅供测试使用的方法 - 停下来,重新考虑
- 测试感觉过于复杂 - 这可能是过度模拟的迹象
铁律
1. NEVER test mock behavior
2. NEVER add test-only methods to production classes
3. NEVER mock without understanding dependencies
4. NEVER create incomplete mocks
5. NEVER treat tests as afterthought
核心反模式类别
1. 测试模拟行为
断言模拟元素,而不是真实行为。修复方法: 测试真实组件,或不要模拟它。 → 核心反模式
2. 生产代码中的仅供测试使用的方法
生产类中只供测试使用的方法。修复方法: 移至测试工具中。 → 核心反模式
3. 在不了解的情况下进行模拟
不了解依赖项/副作用就进行模拟。修复方法: 先了解,再尽量少模拟。 → 核心反模式
4. 不完整的模拟
部分模拟缺少下游代码所需的字段。修复方法: 完整复刻 API 结构。 → 完整性反模式
5. 事后才考虑测试
实现“完成”时却没有测试。修复方法: 使用 TDD——先编写测试。 → 完整性反模式
快速检测清单
提交任何测试前,请运行此清单:
与语言无关的检查:
□ Am I asserting on mock behavior instead of real behavior?
→ TypeScript: testId='*-mock', expect(mock).toHaveBeenCalled()
→ Python: mock.assert_called(), mock.call_count
→ If yes: STOP - Test real behavior or unmock
□ Does this method only exist for tests?
→ TypeScript: destroy(), reset(), clear() only in *.test.ts
→ Python: _set_mock_*, _for_testing only in test_*.py
→ If yes: STOP - Move to test utilities
□ Do I fully understand what I'm mocking?
→ If no: STOP - Run with real impl first, then mock minimally
□ Is my mock missing fields the real API has?
→ TypeScript: Partial<T>, incomplete objects
→ Python: Mock() with few attributes, missing nested fields
→ If yes: STOP - Mirror complete API structure
□ Did I write implementation before test?
→ If yes: STOP - Delete impl, write test first (TDD)
□ Is mock setup >50% of test code?
→ If yes: Consider integration test with real components
参见: 检测指南,了解完整的危险信号和警示迹象。
核心要点
模拟是用于隔离的工具,不是测试对象。
测试模拟行为说明存在问题。修复方法:测试真实行为,或质疑模拟为何必要。
TDD 可避免这些模式。 先编写测试 → 观察失败 → 编写最精简的实现 → 通过 → 重构。
导航
详细反模式分析
检测与预防
特定语言示例
- Python 示例 - 完整的 Python/pytest 指南,涵盖全部 5 种反模式,包括 unittest.mock 和 pytest-mock 模式、fixture 最佳实践,以及 pytest 特定检测。在处理 Python 测试时加载。
相关技能
使用此技能时,可考虑搭配以下技能(如果已部署在你的技能包中):
-
test-driven-development:完整的 TDD 工作流和 red-green-refactor 循环
- 使用场景:践行 TDD,防止反模式
- 集成方式:TDD 工作流从设计上就能防止大多数反模式
- 状态:推荐——此技能已涵盖基本反模式
-
verification-before-completion:完成的定义和验证流程
- 使用场景:确保测试是完成标准的一部分
- 集成方式:工作只有在测试通过后才算完成
- 状态:推荐——强化测试思维
注意:所有技能都可独立部署。即使没有这些技能,此技能也能正常工作。
重要提醒
- Mock 用于隔离,而非证明——测试真实代码,而不是 Mock
- 生产环境会忽略测试——不要添加仅供测试使用的方法
- Mock 之前先了解清楚——了解依赖项和副作用
- Mock 必须完整——完整映射 API 结构
- 测试就是实现的一部分——不是可有可无的事后补充
危险信号——立即停止
出现以下情况时,立即停止:
- 测试 Mock 的行为
- TypeScript:断言
*-mock测试 ID,或使用expect(mock).toHaveBeenCalled() - Python:在未检查真实行为的情况下使用
mock.assert_called()、mock.call_count
- TypeScript:断言
- 添加仅供测试使用的方法
- TypeScript:只在
*.test.ts中出现的destroy()、reset() - Python:带有“For testing only”文档字符串的
_set_mock_*、_for_testing
- TypeScript:只在
- 尚未了解清楚就进行 Mock
- “以防万一”而添加
@patch或vi.mock() - 凭记忆创建 Mock,而不参考 API 文档
- “以防万一”而添加
- Mock 不完整
- TypeScript:使用
Partial<T>,缺少嵌套对象 - Python:对数据对象使用
Mock(),缺少必填字段
- TypeScript:使用
- 把测试当作事后补充
- 表示“测试可以等”或“已经可以测试了”
- 先提交实现,再提交测试
**当 Mock 变得过于复杂时:**考虑使用真实组件进行集成测试。这通常更简单,也更有价值。
与其他技能集成
**前置条件:**Test-Driven Development 技能——TDD 可防止反模式(推荐用于完整工作流) **互补技能:**Verification-Before-Completion 技能——测试即完成(确保遵循正确的测试规范) **特定领域技能:**webapp-testing、backend-testing,提供框架模式(如有,可参阅技能库)