mcpField
T
test-guard

test-guard

github.com/amelnagdy测试与质量1.3k4.2k 次安装17 周前更新
代码仓库

关于 test-guard

Test Guard 是用于检查新增或修改测试代码的 Skill,面向编写测试的编码 Agent 和代码审查者。它着重识别重复、过度模拟和只验证框架行为的测试,并提供按规则组织的审查结果。

主要功能

  1. 01按九项规则审查测试
  2. 02检查模拟是否位于系统边界
  3. 03识别重复及无必要测试
  4. 04审查测试命名与覆盖对象
  5. 05按文件汇总违规及修复建议

适用场景

  1. 01提交前审查新增测试代码
  2. 02精简重复或维护成本高的测试
  3. 03审查测试是否验证项目自身逻辑

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/amelnagdy/guard-skills --skill test-guard

安装后在 Claude Code 中输入/test-guard确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

agents/
openai.yaml
references/
jest.md
llm-app-testing.md
phpunit.md
pytest.md

详细介绍

Test Guard

在生成或修改的测试代码发布前进行审查。在首轮测试编写完成后、测试提交、合并或展示给用户前,执行以下规则。要做敏锐的审查者,而非吹毛求疵的人:指出会增加维护成本或掩盖真实缺陷的问题,忽略纯粹的风格偏好。

制定这些规则,是因为编码 Agent 往往会过度生成测试。常见问题包括:充斥 mock、断言实现细节的单元测试;测试主体几乎重复、仅相差一个值;以及重复验证框架本身而非项目逻辑的测试。这些测试在 diff 中看似工作量充足,却会永久增加维护成本。

此技能的适用时机

  • 编码 Agent 刚刚用任何语言编写了新的测试函数或测试文件
  • 你正在编辑现有测试
  • 你正在审查包含测试变更的 diff
  • 用户要求你编写、添加或审查测试

先适应项目

这些规则具有普适性,但具体应用因项目而异。审查前:

  1. 检查项目自身的 Agent 指引(CLAUDE.md、AGENTS.md)和测试文档。如果项目专属的测试规则与此技能冲突,以项目规则为准。
  2. 确定测试技术栈,然后阅读对应的参考文档,了解具体模式:
  3. 如果项目调用 LLM API、使用 Agent 框架,或接入可观测性/遥测,也要阅读 references/llm-app-testing.md——其中补充了三条针对 LLM 应用的规则。
  4. 梳理项目的系统边界:网络调用、数据库、文件系统、时钟和随机性、第三方 SDK、LLM API。现有的 fixture 和测试辅助工具通常能体现项目已有的边界划分方式。

要做什么

  1. 阅读测试代码:diff、新文件或正在修改的部分。
  2. 根据以下规则逐一检查每项测试。
  3. 简明报告违规项:规则编号、位置、违规原因和建议的修复方式。
  4. 如果用户在编写测试前明确要求使用此技能,就在编写时应用这些规则——不要先写出违规测试再指出问题。

编写新测试时,针对每项测试都要问:“这项测试能捕获什么其他测试都捕获不了的具体缺陷?”如果无法清楚回答,就不要编写这项测试。

九条规则

规则 1:测试行为,而非实现

从调用者的角度测试代码的行为。断言返回值和可观察到的副作用。绝不要断言某个内部辅助函数是否以特定参数被调用——这样的测试每次重构都会失效,却捕获不了任何问题。

违规模式: 断言内部函数的 mock 被调用,而该函数并非系统边界。 修复方式: 断言调用者能观察到的返回值或状态变化。

规则 2:每个 mock 都必须有充分理由

只在系统边界使用 mock:网络和 HTTP 调用、LLM API、数据库、外部文件的文件系统 I/O、时钟和随机性、第三方 SDK。绝不要 mock 内部类或辅助函数来隔离“单元”——人为创建的隔离边界会掩盖值得捕获的集成缺陷。

mock 系统边界时,断言调用者如何处理响应,而不是断言 mock 收到了哪些特定参数。

规则 3:每项测试只覆盖一种场景,变体使用数据驱动

如果两项或更多测试使用完全相同的设置,只在输入/输出值上有所不同,就合并为一个数据驱动测试(@pytest.mark.parametrize、PHPUnit #[DataProvider]、Jest test.each)。

**适合分开编写测试的情况:**设置不同、断言不同、mock 配置不同,或确实属于不同场景,只是碰巧测试了同一个函数。

规则 4:每个测试都必须证明自身的必要性

问问自己:“这个测试能捕获哪些其他测试都无法捕获的 bug?” 删除那些只检查拼写错误、验证数据类的默认值或测试简单直通逻辑的测试。

常见的无正当理由的测试: 构造函数设置属性、函数拒绝类型系统已经禁止的输入、日志消息的字符串格式,以及常量是否等于其字面值。

规则 5:根据场景为测试命名

模式:test_<scenario>_<expected_outcome>。测试名称应像一条需求,而不是照搬函数签名。

不佳良好
test_parse_response_missing_fieldtest_malformed_response_falls_back_to_default
test_get_language_no_classtest_element_without_class_returns_empty_language
test_add_tags_single_stringtest_single_tag_normalizes_to_list
规则 6:生产环境回归测试弥足珍贵

复现真实生产环境 bug 的测试始终有正当理由。在名称或注释中注明相关事件(日期、问题 ID 或简短描述),绝不可删除。这些测试不受规则 4 限制——相关事件就是它们存在的理由。

规则 7:不要测试框架保证的行为

不要测试验证库是否执行验证、ORM 是否提交、路由器是否返回 404,或测试框架的夹具是否正常工作。要测试基于框架实现的自有逻辑。

违规模式: 即使删除项目的所有自定义代码、只保留框架默认行为,测试仍会通过。

规则 8:状态对象和值对象是真实对象,绝不模拟

绝不要模拟数据模型、DTO、实体或状态对象。应构造真实实例。模拟状态会掩盖字段名称拼写错误和验证错误——而这正是值得捕获的 bug。如果构造真实对象很麻烦,那是设计方面的反馈,不是模拟的理由;添加一个小型构建器或工厂辅助函数。

规则 9:测试基础设施时使用真实基础设施

当数据库查询、架构行为或持久化逻辑就是测试对象时,应使用真实测试数据库,并通过夹具应用真实迁移。在这种情况下模拟会话毫无意义。如果持久化只是被测行为的副作用,则可以模拟数据库。

报告格式

标记违规时,使用以下格式:

**Rule N violation** in `tests/path/file.ext::<test_name>`
- What: <one sentence describing the violation>
- Fix: <one sentence describing what to do instead>

按文件归类违规。如果某个文件没有违规,不要提及它。

严重程度指南

违规并非同等严重。请自行判断:

  • 必须修复: 规则 1、2、8——这些规则会掩盖真实 bug 或导致测试脆弱
  • 应该修复: 规则 3、4、5、7——这些问题会造成测试臃肿并增加维护负担
  • 弥足珍贵: 规则 6——绝不删除,始终允许
  • 值得指出: 规则 9——涉及测试架构;应予以标记,但不要因此阻碍小规模更改

参考资料

此技能不做什么

  • 它不会运行测试。请使用项目的测试运行器。
  • 它不会强制执行代码风格——这是代码检查工具的职责。
  • 它不会决定测试什么——只决定如何测试。
  • 除非有人要求审计,否则它不会标记你未修改文件中的既有违规。

评论

支持 Markdown