关于 gjalla-test-audit
gjalla-test-audit 是一项测试套件审查技能,用于发现虚假的信心、重复覆盖和固化错误行为的测试。它指导从了解测试架构到分类报告问题的结构化审计,并可在获批后清理测试。
主要功能
- 01梳理测试结构与层次
- 02发现循环断言和占位测试
- 03对照生产代码检查测试
- 04按严重程度分类问题
- 05报告覆盖缺口与影响
- 06指导获批后的测试清理
适用场景
- 01审查可能掩盖回归的模拟
- 02找出未执行源代码的测试
- 03识别错误断言或测试数据
- 04规划移除重复测试
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ gjalla/ engineering --skill gjalla-test-audit安装后在 Claude Code 中输入/gjalla-test-audit确认已加载。
详细介绍
测试审计
深入审查测试套件质量,找出会造成虚假信心、固化错误、重复覆盖,或过度使用模拟而无法捕获真实回归的测试。
流程
总体而言,按以下步骤操作,然后将关键代码与测试导入交叉核对。可以根据生产环境影响范围(哪些代码依赖最多——如果使用 gjalla,其影响范围和变更历史会一目了然)、近期错误历史,以及失败模式的确定性来确定重要程度。
阶段 1:了解情况
深入分析之前,先了解项目的测试基础设施。
- 梳理测试结构:找出所有测试目录,统计各目录中的文件数量,并识别命名约定(
.test.ts、.pglite.test.ts、.integration.test.ts等) - 识别测试层级:哪些测试使用真实数据库(PGlite、SQLite)?哪些模拟 ORM?哪些在服务边界进行模拟?哪些使用
@vitest-environment node,哪些使用jsdom? - 识别关键组件:哪些是安全边界、数据访问层和核心业务逻辑?这些地方的虚假信心最危险。
阶段 2:排查反模式
并行调查各测试层。对于每个测试文件,同时阅读测试和它声称要测试的源代码。需要查找的反模式:
反模式 1:重新实现逻辑的测试
测试从未导入真实代码,而是在测试中重新定义逻辑并测试自己的副本。迹象:
- 使用
@vitest-environment node,但未导入组件或钩子 - 定义了与源代码逻辑相似的本地函数,名称为
simulate*或handle* - 测试文件没有从
src/或源代码目录导入任何内容
这些测试永远无法捕获回归,因为它们没有执行真实代码。
反模式 2:同义反复的模拟测试
测试将整个数据库/ORM 调用链模拟为硬编码返回值,然后断言这些相同的硬编码值。迹象:
- 对
db.select().from().where()调用链使用mockReturnValue/mockResolvedValue - 基于队列的模拟基础设施(
_setSelectQueue、pushSelectResult) - 断言类似
expect(result).toEqual(mockReturnValue),其中mockReturnValue就是模拟设置的返回值 - 构建器模式模拟会忽略
.from()、.where()、.innerJoin()等方法的所有参数
关键测试:真实代码中的错误(表、列、WHERE 子句或 JOIN 错误)能否导致此测试失败?如果不能,这个测试就是同义反复。
反模式 3:固化错误行为的测试
断言验证了错误行为,而该行为恰好与有缺陷的源代码一致。迹象:
- 测试夹具使用的字段名与源代码不一致(例如,测试使用
assignedTier,而源代码读取subscriptionTier) - 独立测试的服务使用了不一致的阈值
- 模拟返回值掩盖了测试声称要验证的逻辑
- 测试名称表达的含义与断言不符(例如,名称说“返回 403”,却断言
toBe(404))
关键测试:测试模拟数据是否与真实上游代码实际生成的数据一致?还是说,测试数据是人为构造的,只为了匹配(可能有缺陷的)被测函数?
反模式 4:冗余的配套测试
已有更严格的配套文件完全覆盖了这些测试。迹象:
.test.ts文件模拟数据库,而.pglite.test.ts文件针对同一类测试真实 SQL- “集成”测试与“单元”测试在相同层级进行模拟
- 多个测试文件针对同一个源文件,且
describe/it块有重叠
反模式 5:占位测试
expect(true).toBe(true)- 测试名称描述详尽,却没有实际断言
- 调用模拟后只断言该模拟被调用(同义反复)
第 3 阶段:对发现进行分类
将发现整理为以下层级:
| 层级 | 说明 | 操作 |
|---|---|---|
| Tier 1 | 完全没有测试真实代码的测试(重新实现的逻辑、内联模拟处理程序) | 删除整个文件 |
| Tier 2 | 同时包含有用测试和同义反复测试的文件 | 删除同义反复部分,保留逻辑测试 |
| Tier 3 | 有真实配套测试(PGlite、集成测试)的同义反复测试 | 删除冗余的模拟版本 |
| Tier 4 | 没有真实配套测试的同义反复测试 | 标记为危险的虚假信心。需要编写真实测试。 |
| Bug | 在源代码中体现错误行为的测试 | 修复源代码和测试 |
第 4 阶段:报告
以结构化报告的形式呈现发现,包含:
- 体现 Bug 的测试(优先级最高)——这些测试掩盖了真实的生产问题
- Tier 1-3 的删除项,附上文件路径和行数
- Tier 4 的缺口——覆盖率会如实下降、需要补充真实测试的领域
- 影响分析:哪些方面会更稳健、可能暴露哪些 Bug、覆盖率会受到什么影响
第 5 阶段:清理(如获批准)
分批执行,每批之间运行测试:
- 删除 Tier 1 文件(未测试任何真实代码)
- 移除 Tier 2 中的同义反复部分
- 移除 Tier 3 中的冗余测试(存在配套测试时)
- 修复体现错误行为的测试,并修复源代码中的 Bug
- 运行覆盖率检查,找出真实缺口
- 为 Tier 4 缺口编写真正的测试(数据库依赖代码使用 PGlite)
原则
- 无法失败的测试比没有测试更糟。 它会徒增信心,却无法提供保护。
- 在边界处模拟,而非内部实现。 模拟外部服务(Supabase、Stripe、GitHub API)。能使用 PGlite 时,不要模拟自己的数据库层。
- 往返测试能发现键名不匹配。 当函数 A 写入的数据由函数 B 读取时,应将 A 的实际输出作为 B 的输入,联合测试这两个函数。手工编写的测试数据可能悄无声息地引入 Bug。
- 同义反复的测试会让覆盖率数字失真。 如果模拟拦截了所有有意义的操作,那么某一行就不算“已覆盖”。真实的覆盖率来自执行真实代码路径的测试。
- 先删除,再编写。 先消除虚假信心,让覆盖率报告如实反映优势和风险,再填补缺口。
评论
支持 Markdown