mcpField
T
test-audit

test-audit

github.com/t0msilver测试与质量191 次安装今天更新
代码仓库

关于 test-audit

面向编写或审查测试的开发者,强调测试应能独立发现与用户相关的缺陷,并提供测试设计、回归覆盖、模拟和审计既有测试的准则。

主要功能

  1. 01编写测试前的四项检查
  2. 02回归测试验证
  3. 03模拟使用指导
  4. 04基于变异的覆盖检查
  5. 05基于证据的测试审计

适用场景

  1. 01评估新测试是否能保护行为
  2. 02验证回归测试能否复现缺陷
  3. 03依据记录的证据精简测试

安装

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

$npx skills add https://github.com/t0msilver/skills --skill test-audit

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

包含的文件

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

reference/
campaign.md
junk-patterns.md
sources.md

详细介绍

测试审查

测试通过捕获人们会称为 bug 的问题,证明其维护成本物有所值。编写测试和决定删除哪些现有测试,都适用同一标准。若要在一次改动中精简整个子系统的测试,请先阅读 reference/campaign.md。

编写测试之前

回答以下四个问题;只要有一个问题答不上来,就先不要添加测试。

  1. 什么生产代码改动会让它失败?这种改动是 bug,还是一种决策? 如果只有有意做出的决策才会让它失败(常量的值、确切措辞、私有结构),那它就是变更探测器:重设计时会触发,出现 bug 时却不会。应改为测试依赖该决策的行为:不要测 MAX_RETRIES == 5,而要测“不会发生第六次尝试”。
  2. 预期值从何而来? 应来自字面值、计算示例或规范。绝不能来自被测代码或其辅助函数:expect(f(x)).toBe(f(x)) 必然会通过。使用实现自身的公式重新计算预期值,也会把该公式中的 bug 一并带入。
  3. 为什么现有覆盖无法捕获它? 每项契约都应由一个测试在最合适的边界进行验证,通常是公共接口。增加第二层测试,必须有其所属测试无法触及的风险,例如传输或生命周期故障。与其新增近似重复的测试,不如在现有表格测试中增加一行。
  4. 它是否需要生产代码调用方并不需要的生产代码接缝? 例如为了测试而添加的导出、标志、getter、重置钩子或 destroy()。如果是,应改为在真实边界进行测试;仅测试清理所需的内容应放入测试工具中。

然后根据 垃圾测试模式 检查。若命中其中一种模式,就不符合准入标准;除非保留标准明确指出它独立保护的契约。如果测试会因保持行为不变的重构而失败,那它断言的就是实现细节;合并前,应在所属边界重写测试。

不要测试框架(例如断言路由器会调用你注册的处理程序),也不要测试琐碎代码:只有当构造函数、getter 和单纯的转发逻辑会进行验证、规范化、设定默认值、派生数据或产生副作用时,才值得为它们编写测试。

回归测试

回归测试必须在修复前的代码上失败,失败原因应与 bug 描述一致,并在修复后通过。应在旧代码上运行测试来验证。若测试因 bug 不会导致的问题而失败(导入失败、缺少选择器、设置损坏),就无法证明任何东西;应修复测试,直到它以与 bug 相同的方式失败。始终没有失败过的回归测试,证明的只是 mock,而不是修复有效。在所属边界编写一个测试;不要在它经过的每一层重复同一场景。

Mock

  • 绝不要断言 mock。若断言只会在 mock 存在时通过、移除 mock 时失败,那它对你的代码毫无证明作用。
  • Mock 方法之前,先列出它的副作用。应 mock 测试所依赖层级之下的慢速或外部层,而不是 mock 方法本身。
  • Mock 响应应完整复现真实结构,而不只是包含该测试会读取的字段;不完整的 mock 可能通过测试,而集成却会失败。
  • 当参数、调用次数或顺序属于契约时,应对它们进行断言。成功、错误和格式错误等每个分支都应有各自的 fixture,避免错误的分支也能满足测试。
  • 如果 mock 设置比测试本身还复杂,或者你说不清为什么需要 mock,就改用真实组件,并配合虚拟网络或文件系统。

完成之前

在脑中修改生产代码:错误的常量或参数、错误的分支、缺失的副作用、空返回值,以及缺少对空值、零、null、未授权或格式错误输入的检查。每一种情况都至少应有一个测试失败。若某种修改没有被任何测试捕获,就说明有行为未受保护,或测试是恒真式。

审查现有测试

  1. 阅读根目录和作用域内的 AGENTS.md/CLAUDE.md,然后针对每个候选测试,阅读完整测试、它覆盖的生产代码、调用方、重叠测试、CI 路由以及用于了解其存在原因的 git log。如果测试声称验证了依赖项支持的行为,还要阅读该依赖项的源代码或类型定义。
  2. 发现阶段保持只读。优先选择少数证据充分的候选项,而不是列出一长串推测性候选项。范围较广时,按领域拆分任务,并行安排只读 Agent。
  3. 编辑前,记录每个候选项的证据。缺少任何字段,都说明该候选项尚未准备好删除。
  4. 每次变更只编辑一个连贯的批次。删除测试专用的导出、标志、包装器,以及因删除而不再需要的无用生产代码路径,而不是保留别名。将保留的回归测试移到所属测试套件。不要添加重复描述同一实现的替代测试。
  5. 运行最小范围的所属测试和同级测试,然后运行仓库对已变更文件要求的检查。删除源码文本断言时,运行负责实际契约的脚本或试运行。
  6. 分别报告生产代码和测试代码的行数变化(git diff --numstat),并列出保留的、看似无用的测试及其保留理由。

注意事项

  • 不能仅因测试是静态的或运行缓慢就删除。 读取源码文本的测试,可能是针对面向用户的键、字节或路径最廉价的独立保护措施。如果契约发生变化时它会失败,并且重命名标识符后仍能发挥作用,就应保留。其他测试应符合保留标准。
  • 如果某个删除候选测试在基线分支上失败,可能是产品缺陷。 重现该问题并修复生产代码;不要删除发现问题的测试。
  • 根据断言判断测试,而不是根据名称。 一个名为“退役窗口”的测试,曾经断言窗口没有被清除。
  • 检查负向测试是否确实因正确原因通过。 如果拒绝是由其他防护条件触发,或者生产路径根本不会走到被拒绝的环节,那么测试虽然通过,却没有保护任何内容。
  • 不要为了减少数量而删除测试。 对不确定的候选项,暂且保留。优先确保剩余内容可信。
  • 测试套件运行期间,不要在同一个检出目录中更改测试。 监视模式和并行运行器可能会读取只编辑了一半的文件,导致报告并不存在的失败。

评论

支持 Markdown