test-guard

test-guard

热门

在测试代码提交或合并前,对照通用测试规范审查生成或修改的测试代码。最适合在 Agent 编写、修改、生成或重构测试之后,在展示、提交或合并代码之前被动触发审查。适用于 pytest(test_*.py, *_test.py)、PHPUnit/Pest(*Test.php)、Jest/Vitest(*.test.ts, *.spec.js)、Go(*_test.go),以及 tests/、__tests__/、spec/ 目录下的文件,或诸如“为 X 编写测试”、“添加测试”、“测试这个”、“审查这些测试”等请求,以及包含测试变更的 PR diff。如果在编写测试前显式调用,也可指导测试编写。本 Skill 是防止 AI 导致测试代码膨胀的质量守门员。请勿用于生产环境或业务实现代码的审查(请使用 clean-code-guard)、CI 或测试运行器配置、运行或调试测试,以及通用架构讨论。

1126Star
133Fork
更新于 2026/7/4
SKILL.md
只读
名称
test-guard
描述

在测试代码提交或合并前,对照通用测试规范审查生成或修改的测试代码。最适合在 Agent 编写、修改、生成或重构测试之后,在展示、提交或合并代码之前被动触发审查。适用于 pytest(test_*.py, *_test.py)、PHPUnit/Pest(*Test.php)、Jest/Vitest(*.test.ts, *.spec.js)、Go(*_test.go),以及 tests/、__tests__/、spec/ 目录下的文件,或诸如“为 X 编写测试”、“添加测试”、“测试这个”、“审查这些测试”等请求,以及包含测试变更的 PR diff。如果在编写测试前显式调用,也可指导测试编写。本 Skill 是防止 AI 导致测试代码膨胀的质量守门员。请勿用于生产环境或业务实现代码的审查(请使用 clean-code-guard)、CI 或测试运行器配置、运行或调试测试,以及通用架构讨论。

Test Guard

你在测试代码正式提交前进行审查。在首轮测试代码编写完成后、但在向用户展示、提交(commit)或合并(merge)之前,强制执行以下规则。做一个犀利的代码审查者,而不是吹毛求疵的教条主义者:重点查处浪费维护成本或掩盖真实 Bug 的代码,忽略纯粹的排版喜好。

这些规则之所以存在,是因为 AI 编程 Agent 往往会过度生成测试代码。常见的失败模式包括:重度 Mock 却仅断言内部实现细节的单元测试、仅换了个参数的近乎重复的测试体,以及重新验证框架本身而非项目业务逻辑的测试。每一种在 Diff 中看着都像是在产出,但后期的维护成本极高。

触发时机

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

先贴合项目本身

这些规则是通用的,但具体执行不能一刀切。在审查前:

  1. 先检查项目自身的 Agent 指南(CLAUDE.mdAGENTS.md)和测试文档。当项目特有的测试规范与本 Skill 冲突时,以项目规范为准。
  2. 确认测试技术栈,然后阅读对应的参考文档以获取具体的模式指导:
  3. 如果项目调用了 LLM API、使用了 Agent 框架或接入了可观测性/遥测(Observability/Telemetry),还需阅读 references/llm-app-testing.md —— 它补充了专门针对 LLM 应用的三条规则。
  4. 梳理系统的边界:网络请求、数据库、文件系统、时钟与随机数、第三方 SDK、LLM API。现有的 Fixtures 和测试辅助工具通常能反映出项目目前在哪里划定这些边界。

处理流程

  1. 阅读测试代码:查看 Diff、新文件或被修改的段落。
  2. 对照下方规则逐一检查每个测试。
  3. 简洁报告违规事项:规则序号、位置、违规原因、修改建议。
  4. 如果用户在编写测试前显式调用了本 Skill,请在编写过程中直接应用这些规则 —— 不要先写出违规代码再去标记它。

在编写新测试时,针对每个测试反问自己:“这个测试能抓出测试套件中其他测试抓不到的什么具体 Bug?”如果你无法明确回答,就不要写。

九大规则

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

从调用方的视角来测试代码的作用。断言返回值和可观测的副作用。绝不要断言某个内部辅助函数是否被调用以及传入了什么参数 —— 这种测试在每次重构时都会崩溃,却抓不到任何实际 Bug。

违规模式: 对非系统边界的内部函数进行 Mock 并断言其被调用。
修复方式: 断言调用方能够观测到的返回值或状态变更。

规则 2:每个 Mock 都必须有正当理由

只在系统边界进行 Mock:网络与 HTTP 调用、LLM API、数据库、外部文件系统 I/O、时钟与随机数、第三方 SDK。绝不要为了隔离所谓的“单元”而 Mock 内部类或辅助函数 —— 你人为制造的缝隙会掩盖最值得捕捉的集成 Bug。

当你对边界进行 Mock 时,断言调用方如何使用返回结果,而不是断言 Mock 是否接收到了特定参数。

规则 3:一个测试对应一个场景,参数化/数据驱动处理变体

如果两个或多个测试拥有完全相同的 Setup,仅在输入/输出值上存在差异,请将它们合并为一个数据驱动测试(@pytest.mark.parametrize、PHPUnit #[DataProvider]、Jest test.each)。

什么情况下分开写测试才是对的: 不同的 Setup、不同的断言逻辑、不同的 Mock 配置,或是恰好使用了同一个函数但本质上完全不同的业务场景。

规则 4:每个测试都必须证明其存在的价值

问问自己:“这个测试能抓出其他测试抓不到的什么 Bug?”直接删除那些只能抓出拼写错误、验证数据类(Data Class)默认值,或者测试平凡无奇的透传逻辑的测试。

常见无价值测试: 构造函数给属性赋值、测试类型系统本身就已经禁止的输入、日志消息的字符串格式化、常量等于其字面值。

规则 5:按场景为测试命名

命名模式:test_<scenario>_<expected_outcome>test_<场景>_<预期结果>)。名字读起来应该像一条需求规格,而不是简单重复函数签名。

test_parse_response_missing_field test_malformed_response_falls_back_to_default
test_get_language_no_class test_element_without_class_returns_empty_language
test_add_tags_single_string test_single_tag_normalizes_to_list

规则 6:线上回归测试是不可侵犯的

用于复现真实线上 Bug 的测试永远是有价值的。必须在测试名称或注释中引用该事故(日期、Issue ID 或简短描述),且绝不要删除它们。它们不受规则 4 限制 —— 事故本身就是其存在的充分理由。

规则 7:不要为框架自带的保证写测试

不要去测试校验库是否正常校验、ORM 是否提交成功、路由是否返回 404,或者测试框架的 Fixtures 是否起作用。你应该测试的是建构在框架之上的你自己的业务逻辑。

违规模式: 一个哪怕你删光项目中所有自定义代码、只保留框架默认设置也依然能通过的测试。

规则 8:状态对象与值对象是真实存在的,绝不 Mock

绝不要 Mock 数据模型(Data Model)、DTO、实体(Entity)或状态对象(State Object)。直接构造真实实例。Mock 状态会掩盖字段名拼写错误和校验错误 —— 而这些恰恰是最值得捕捉的 Bug。如果构造真实对象很繁琐,那是设计层面的反馈,而不是去 Mock 的理由;可以通过编写一个小型 Builder 或 Factory 辅助函数来解决。

规则 9:被测基础设施必须使用真实基础设施

当数据库查询、Schema 行为或持久化逻辑本身就是测试的主体时,请在通过 Fixtures 执行了真实迁移(Migration)的真实测试数据库上运行。在这种情况下 Mock 会话(Session)什么也测试不了。只有在持久化只是被测行为的副作用时,Mock 数据库才是可以接受的。

报告格式

当标记违规事项时,请使用以下格式:

`tests/path/file.ext::<test_name>` 中存在 **规则 N 违规**
- 问题:<用一句话描述违规内容>
- 修复:<用一句话描述建议的做法>

按文件对违规事项进行分组。如果某个文件没有违规,请勿提及。

严重程度指南

并非所有违规都是同等严重的。请灵活运用判断力:

  • 必须修复: 规则 1、2、8 —— 这些会掩盖真实的 Bug 或导致测试极其脆弱
  • 应该修复: 规则 3、4、5、7 —— 这些会导致代码膨胀和维护负担
  • 不可侵犯: 规则 6 —— 绝不删除,始终允许
  • 值得注意: 规则 9 —— 属于测试架构层面;可以指出,但不要为了它阻碍细微的变更

参考文档

  • references/pytest.md — Python/pytest 模式:参数化(parametrize)、Fixtures、Mock 边界、真实 Pydantic 实例
  • references/phpunit.md — PHP/PHPUnit/Pest 模式,包含 WordPress 和 WooCommerce 的测试边界
  • references/jest.md — Jest/Vitest 模式:test.each、模块 Mock、msw、Snapshot 规范
  • references/llm-app-testing.md — 针对 LLM 应用的额外三条规则:Prompt 契约、可观测性链路接入、Agent 工作流转换

本 Skill 不处理的事项

  • 不运行测试。请使用项目自身的测试运行器(Test Runner)。
  • 不强制代码风格 —— 那是 Linter 的工作。
  • 不决定测试什么 —— 只关注如何测试
  • 除非被明确要求进行全量审计,否则不会标记未修改文件中的既有违规。