首页
/ 用 gstack Testing Specialist 清单做系统化测试缺口审查:把「没测到」变成可复现的代码评审结论

用 gstack Testing Specialist 清单做系统化测试缺口审查:把「没测到」变成可复现的代码评审结论

2026-09-06 18:03:11作者:农烁颖Land

导读

本文讲解 gstack 中 Testing Specialist Review Checklist 这份评审专家清单:它定义了一个专职审查测试质量的 AI 子代理,在合入前的代码评审(/review,即 Pre-Landing Review)中对 diff 进行六类系统性扫描,找出「新错误处理路径没有测试」「边界值没有覆盖」「测试相互污染」「测试偶发失败」「安全强制逻辑无验证」「覆盖率空洞」等问题,并以机器可解析的 JSONL 输出协议逐条产出结论。读完本文,你将掌握这份清单的完整检查范畴、JSON 输出 Schema 的每个字段语义、它如何与 gstack Review Army 并行子代理体系协同(含测试桩 test_stub 的生成与去向),以及仓库中对应的端到端测试如何验证这一机制。

一、定位:Testing Specialist 是 /review 的常驻专家

gstack 的 review/SKILL.md 将合入前评审组织为多道关卡:Step 4 的主检(Critical Pass + Informational 分类)覆盖 SQL 与数据安全、竞态条件、LLM 输出信任边界等结构化风险;Step 4.5 则启动 Review Army(评审军团),向若干专职子代理(specialist)分发各自领域的检查清单。

Testing Specialist 在其中处于默认常驻的位置。依据 review/SKILL.md 的调度规则,当 diff 变更行数 ≥ 50 时,有两个专家每次评审必派

  1. Testing —— 读取 review/specialists/testing.md
  2. Maintainability —— 读取 review/specialists/maintainability.md

对应的分支逻辑在源码中写作:

Always-on (dispatch on every review with 50+ changed lines):
1. Testing — read review/specialists/testing.md
2. Maintainability — read review/specialists/maintainability.md

DIFF_LINES < 50 时则不派发任何专家,直接输出 "Small diff (N lines) — specialists skipped." 并进入 Step 5。Testing Specialist 自己的文档头部把适用范围标注为 "Always-on (every review)",而 Review Army 的整体调度对它做了「小 diff 不派发」的现实约束,避免为一行改动付出子代理成本。

除此之外还有按作用域信号条件派发的专家:Security(SCOPE_AUTH=true 或后端改动超 100 行)、Performance、Data Migration、API Contract、Design 等,各有独立清单文件,例如 review/specialists/security.md。这些专家通过 Agent 工具并行启动(在一条消息中发起多个 Agent 调用),每个子代理拥有全新上下文,不带主检的先入之见。

二、输出协议:JSONL Finding 与 NO FINDINGS 哨兵

Testing Specialist 的输出不是散文,而是严格的一段 JSON 一行(JSONL)。整份清单第 4-7 行定义了协议:

{"severity":"CRITICAL|INFORMATIONAL","confidence":N,"path":"file","line":N,"category":"testing","summary":"...","fix":"...","fingerprint":"path:line:testing","specialist":"testing"}

字段语义逐项拆解:

字段 必填 取值/格式 含义
severity CRITICALINFORMATIONAL 严重度:导致缺陷外泄的为 CRITICAL,质量改进型为 INFORMATIONAL
confidence 1–10 整数 置信度,纳入统一校准体系(9–10 正常展示;5–6 需附 caveat;3–4 移入附录;1–2 除非 P0 否则不报)
path 文件路径 问题所在文件
line 行号 问题行号
category testing 该专家所有 finding 的类别固定为 testing
summary 一句话 问题描述
fix 一句话 建议修复
fingerprint path:line:testing 去重指纹,用于跨专家、跨评审轮次的查重
specialist testing 来源专家标识
evidence 证据文本 佐证材料
test_stub 测试骨架代码 能捕获该问题的测试桩,见下文第五节

协议还有一条硬性纪律:如果没有发现任何问题,只输出 NO FINDINGS,不要输出任何其他内容——不能有前言、不能有总结、不能有注释性旁白。这与 review/checklist.md 中 "No compliments — just the problems" 的原则一致,保证下游解析器(Step 4.6 按行解析 JSON)能稳定消费输出。

三、六大审查范畴详解

Testing Specialist 的检查主体是六类测试缺陷,每类包含一组可操作的判别点。以下结合仓库上下文逐一展开。

3.1 Missing Negative-Path Tests(缺少负路径测试)

只测了「应该成功」,没测「应该失败」。这是测试体系最常见的系统性空洞。

判别点包括:

  • 新增的错误/拒绝/非法输入处理路径没有任何对应测试——写了错误分支却从不验证它触发;
  • Guard clause(守卫子句)和早期 return 未测试——if invalid then return 这类提前退出常常是「从未执行过的死逻辑」;
  • try/catch、rescue、错误边界(error boundary)中的错误分支没有失败路径测试——只覆盖 try 的成功流;
  • 代码中断言的权限/认证检查,从未测试「被拒绝(denied)」那一侧——见第六节「安全强制测试缺失」。

仓库的端到端测试对此有直接验证。在 test/skill-e2e-review-army.test.ts 的 Consensus 场景(第 494-559 行)中,构造了一个存在 SQL 注入的认证控制器(AuthController#login 用字符串插值拼 User.find_by),场景说明明确指出该漏洞应当被两个专家同时捕获:Security 专家看到注入向量,Testing 专家看到「认证绕过没有测试」。评审输出中若同一 finding 被多视角同时命中,须标记为 MULTI-SPECIALIST CONFIRMED 并列出确认的类别。

3.2 Missing Edge-Case Coverage(缺少边界用例覆盖)

判别点包括:

  • 边界值:零、负数、max-int、空字符串、空数组、nil/null/undefined
  • 单元素集合——循环上的 off-by-one(差一错误)常在空集合与单元素集合处暴露;
  • 面向用户输入中的 Unicode 与特殊字符——emoji、组合字符、控制字符、超长串;
  • 并发访问模式没有竞态测试——见主清单中竞态类别(如 check-then-set、无唯一索引的 find-or-create)的测试侧补充。

这些边界值检查与 review/checklist.md 的 Completeness Gaps 类别互相呼应:后者要求对「增加缺失测试只需照抄 happy-path 结构的 lake 而非 ocean」型缺口给出提示,而 Testing Specialist 负责在代码层面把这类缺口逐一指认。

3.3 Test Isolation Violations(测试隔离违规)

一个测试的结果偷偷取决于另一个测试先跑了什么。今天绿,明天红,随机化顺序就红。

判别点包括:

  • 共享可变状态的测试:类变量(class variables)、全局单例、不清理的数据库记录;
  • 顺序依赖测试:按顺序跑通过,随机化后失败;
  • 依赖系统时钟、时区或 locale 的测试——换台机器或换个时区就崩;
  • 发真实网络请求而不是用 stub/mock 的测试

3.4 Flaky Test Patterns(偶发失败模式)

判别点包括:

  • 时序断言sleepsetTimeoutwaitFor 配过紧的 timeout——在 CI 慢机器上必现的假阳性源;
  • 对无序结果做顺序断言:hash 键序、Set 迭代序、异步解析完成序都不可靠;
  • 依赖外部服务(API、数据库)且无 fallback 的测试
  • 随机测试数据无种子(seed)控制——复现不了就修不了。

3.5 Security Enforcement Tests Missing(缺少安全强制测试)

这条是「负路径测试」在安全维度的特化,判别点包括:

  • 控制器中的 auth/authz 检查没有「未授权」用例测试
  • 限流逻辑没有能证明它确实会拦截(blocks)的测试
  • 输入净化没有恶意输入测试
  • CSRF/CORS 配置没有集成测试

正如清单所说,这类缺陷与主检 Pass 1 的「信任边界」视角互为表里:主检负责发现代码层的漏洞模式,Testing Specialist 负责发现「防护已经写上去了、但从未被测试证明有效」的隐患。Security 专家与 Testing 专家在此处高度互补——review/specialists/security.md 专注抓 authz 绕过与攻击面扩张的实现缺陷,Testing 清单则追「denied / unauthorized / malicious」这些反面用例是否存在。

3.6 Coverage Gaps(覆盖率空洞)

判别点包括:

  • 新增公开方法/函数测试覆盖为零
  • 被修改的方法,既有测试只覆盖旧行为、没覆盖新分支——最典型的回归漏网点;
  • 被多处调用的工具函数只被间接测试——直接路径没有断言,行为漂移不会被发现。

从源码结构看,这一条特别契合 gstack 自述的 Completeness Principle(Boil the Ocean) 哲学:AI 让完整覆盖变得廉价,因此「完整版」才是目标——新增公开方法应当有直接测试,改动的方法应当补新分支用例,多调用点工具函数应当有面向契约的直接测试,而非依赖偶然的间接覆盖。

四、六类问题之外的元约束:依赖主检的职责边界

Testing Specialist 不是万能的。它的清单在设计上刻意避开主检(Critical Pass)已经覆盖的 SQL 注入、竞态、LLM 输出信任边界、Shell 注入、枚举完整性等类别——这些由 review/SKILL.md Step 4 的 CRITICAL 通道处理,专家清单则聚焦「测试本身」的缺陷。与之配套的纪律来自主清单 review/checklist.md 的声明:Specialist categories(Test Gaps 等)由并行子代理处理,不属于主检清单,即主检遇到测试缺口类问题时不应在自有输出中重复造轮子。

同时,所有专家 finding 统一接受 review/SKILL.mdPre-emit verification gate(#1539 反假阳性门):凡要进入报告,必须引用触发该结论的具体代码行(file:line + 原文)。若引不出动机行,则视为未验证,置信度强制压到 4-5、只进附录。这同样约束 Testing Specialist——「这个新方法没有测试」的断言必须指出方法定义所在文件与行号,否则不能以高置信度上报。

五、Finding 的旅程:从 JSON 到修复动作

Testing Specialist 输出的每行 JSON 不是终点,而是接入下游流水线:

  1. 指纹去重与共识加权(Step 4.6):以 fingerprint(缺省回退到 path:line:category)分组。若 Security 与 Testing 同时命中同一指纹,保留最高置信度者并标注 MULTI-SPECIALIST CONFIRMED,置信度 +1(封顶 10)。这正是 test/skill-e2e-review-army.test.ts 中 SQL 注入 + 认证无测试场景验证的行为。

  2. 测试桩(test_stub)与框架感知:Testing Specialist 被要求「凡是能写出捕获该问题的测试,就把骨架放进 test_stub 字段」——先由 review/SKILL.md Step 4.5 检测测试框架(TEST_FW:jest / vitest / rspec / pytest / go-test,依据 jest.config.*vitest.config.tsspec/pytest.inigo.mod 等信号),子代理据此生成 describe/it/test 骨架。携带 test_stub 的 finding 会被强制重分类为 ASK(见 Step 5a:Test stub override),呈交用户审批后再落盘,测试文件路径按项目惯例推导(RSpec 用 spec/、Jest/Vitest 用 __tests__/、pytest 用 test_ 前缀、Go 用 _test.go 后缀;文件已存在则追加)。

  3. Fix-First 分类与动作:参照 review/checklist.md,机械性修复直接 AUTO-FIX,歧义项批量 AskUserQuestion(每项 A) Fix as recommended / B) Skip)。主检里 Critical 偏 ASK、Informational 偏 AUTO-FIX;Testing 专家的多数缺口类 finding 属于可机械补测试的场景,天然落在 AUTO-FIX 侧。

  4. 质量分与档案:全部合并后计算 quality_score = max(0, 10 - (critical×2 + informational×0.5)),并把每个专家的派发统计(dispatchedfindingscriticalinformational)与逐条 action 记录(auto-fixed / fixed / skipped)写入 review-log,供 /ship 识别本分支已完成 Eng Review。

六、把清单用起来:落地建议

  • 作为人类 Reviewer 的自查表:六类范畴可直接移植到任何 PR 的测试审查中。实践中最高频命中的是 3.1(守卫子句无负路径测试)与 3.6(改动方法只测旧行为)——建议按 diff 中每个新增 if error 分支逐个问「反面用例在哪」。
  • 作为测试补充任务清单:对每个 test_stub 生成完整用例后,用随机化顺序(如 RSpec 的 --order random、Go 的 -shuffle)跑一遍即可顺带暴露 3.3 的隔离违规。
  • 与安全评审联动:凡 Security 专家报出 authz/限流/净化类实现缺陷时,检查对应反面测试是否已存在;不存在则按 3.5 单独开一条 finding,这正是 Review Army 设计的多专家互补意图。

相关文件索引

登录后查看全文
热门项目推荐
相关项目推荐