Q&A 10 个关键问题
-
Q:这个 skill 给谁用? A:OpenClaw 仓库内的 AI 智能体(.agents 体系),用来自动评审、新增、清理测试代码。 -
Q:Authoring mode 什么时候触发? A:每次新增、修改测试代码时,作为前置门禁。 -
Q:怎么区分 “好测试” 和 “实现细节测试”? A:行为不变的重构操作,如果测试失败 → 属于实现细节测试。 -
Q:回归测试最重要一条约束是什么? A:必须在 bug 修复前版本可以真实失败;如果 mock 永远不会失败,这个回归测试无效。 -
Q:Campaign 模式和普通 Audit 模式区别? A:普通审计零散挑选高风险测试;Campaign 是一次性清理整个子系统全部测试,风险更高,需要前置阅读 CAMPAIGN.md。 -
Q:扫描阶段能不能直接删代码? A:不能,Discovery 是只读收集证据,编辑动作放在后面。 -
Q:慢、执行时间长的测试是否直接删除? A:不是,运行速度不作为删除理由,只看它是否保护独立契约。 -
Q:删除测试时必须收集证据吗? A:强制,缺少证据字段,禁止执行删除。 -
Q:审计清理的目标 KPI 是删除更多测试行吗? A:不是,目标是提升代码置信度;禁止为了删代码而清理不确定候选。 -
Q:审计完成交付物是什么? A:结构化报告,包含清理分类、生产简化、保留理由、代码行数统计、后续待办。
这是 OpenClaw 项目给 AI 智能体(Agent)用的测试审计技能定义,放在仓库 .agents/skills/test-audit/SKILL.md,用来约束 AI 在新增、修改、评审、清理代码测试用例时的行为,本质是一套AI 执行测试治理的标准化操作手册。
核心总纲:3 种模式,统一价值标尺
Test Audit 有三种工作模式,所有模式共用一套价值判断标准:
- Authoring mode(编写门禁,写测试时触发)
新增 / 修改测试的前置校验,写代码阶段就拦住劣质测试 - Audit mode(审计模式)
存量测试扫描,定位低价值、耦合实现、重复的测试,以及只为测试而暴露的生产侧钩子(test-only production seams);大范围审计拆成独立、清晰的后续 PR,目标是提升置信度,不是追求删多少行 - Campaign mode(专项清理战役模式)
一次性清理整个子系统全部测试(插件 / 核心模块名下所有测试文件),启动前必须阅读 CAMPAIGN.md
一、Authoring gate|编写门禁(新增测试强制四问)
增加任何测试前,必须回答 4 个问题,缺一个就不能写这个测试
-
这个测试保护哪个可观测行为、不变量、独立契约? -
什么真实的回归缺陷会让这个测试失败? -
现有测试覆盖为什么抓不住这个故障? 每个契约有一个主测试边界;只有风险独立(如传输、生命周期故障,主边界测不到)才需要在其他层新增测试。优先用表驱动用例 / 复用 fixture,不要写近似重复的测试;在同一次提交合并重复的前置准备代码。
-
是否需要生产侧专属测试钩子(导出变量、开关、包装器、注入入口),而生产业务代码本身不需要这个钩子? 如果是:不要新增这个钩子,把测试移到真实业务边界上。
四问通过后,再对照【垃圾模式清单】检查:只要匹配垃圾模式,直接拒绝新增;除非满足【保留标尺】,证明它独立守护一份契约。
关键原则:重构(不改变外部行为)就会失效的测试,测的是实现细节,不是业务行为,需要重写
Bug 回归测试额外规则
-
回归测试必须在修复前的代码上可复现失败,修复后通过;只验证 mock 而无法真实失败的回归测试没有价值 -
在归属边界写一条回归用例覆盖 bug 即可,不要在调用链路的每一层重复写同一场景
二、Junk patterns|垃圾测试模式清单(新增门禁拦截,存量审计搜寻目标)
审计和新增测试共用这个检查清单,命中即为劣质测试
-
只有覆盖率探测、没有断言的测试 -
自比较、身份拷贝类断言 -
复制粘贴的 fixture、清单、导出列表 -
硬编码源码、import、字符串文本匹配 (grep) 断言 -
在多个边界重复校验私有判断函数 / 调用形态 -
对同一个契约重复执行断言 -
在模块本地重复实现公共辅助函数逻辑 -
仅为保留 “测试专用导出、全局变量、包装器” 而存在的测试 -
仅被测试调用、生产代码从不调用的死代码 -
期望值由被测辅助函数 / 渲染器本身生成 -
Mock 直接实现断言预期行为,或者同一个 mock 硬扛多个不同 API -
fixture 预先给出回调顺序、存储内容,而本该由业务逻辑自己生成;断言存储,但业务路径根本不会写入这个存储 -
能力测试只是重复声明开关标记,不真正验证标记承诺的交付 / 确认行为 -
阴性用例(负向用例)因为无关原因通过:比如是别的拦截逻辑拒绝,而不是当前业务路径预期拒绝 -
命名 /fixture 夸大能力:例如名字叫 “窗口回收”,实际只断言窗口没有被清空
三、Value bar|价值标尺
测试必须通过维护成本换取价值:保护可观测行为、可信回归场景、独立业务契约。
存量测试:如果仅仅是不修改行为的代码重构就要改动测试 → 这个测试可疑,但不代表直接删除;这条规则只拒绝新增同类测试
审计前必须完整阅读:测试代码、对应生产代码归属、入口、调用方、被调用逻辑、同类实现、重叠测试、CI 路由、提交历史;阅读根目录和作用域内 AGENTS.md。如果测试宣称依赖外部组件行为,要直接看依赖源码 / 类型定义。
四、Discovery|发现扫描阶段
只读,只收集证据,先报告,不修改代码。大范围扫描可以并行分赛道:
-
core & packages(src/, packages/) -
plugins(extensions/) -
UI、应用、脚本、工具链 -
跨横切模式扫描
非专项战役模式:优先少量高风险候选,不要批量找大量不确定目标;重点搜寻上面的垃圾模式。
五、Retention bar|保留标尺(什么测试不能删)
满足任意一条,保留测试:
-
独立校验公共 API、插件 SDK、协议、配置、数据迁移、存储、安全、平台默认值、字节 prompt、跨语言生成代码、包、发布、架构契约 -
顺序是可观测行为时,校验调用顺序的测试 -
可复现真实故障的回归用例 -
源码检查类测试:作为最低成本独立守卫;契约变更就失败,单纯重命名标识符重构不会破坏测试
保留的测试如果基线版本就失败:优先判定为产品 bug,修复业务代码,而不是删测试
⚠️ 静态慢、运行耗时不是删除理由;看起来像测实现细节的测试,有可能本身就是契约校验,删之前要充分举证。
六、Candidate evidence|待删除测试候选证据清单
修改代码前,下面所有字段必须收集齐全,缺一项就不能删
-
测试全名 + 文件路径 -
它实际可以捕获哪类故障 -
被覆盖的生产 / 支撑代码,非测试侧调用方 -
剩余更强的归属边界证明,或者说明为什么不再需要这个校验 -
相关提交历史、该测试 / 钩子当初创建的原因 -
删除这个测试,可以同步清理哪些生产 / 测试支撑代码 -
风险评估 + 最小验证命令
七、Edit shape|修改形态(清理代码规范)
-
按同一个业务归属边界批量处理,提交保持内聚 -
删除废弃的测试专用导出、全局变量、包装器、死生产代码,不要保留别名 -
保留的回归测试迁移到规范归属边界 -
把分散的包 / 依赖断言合并为通用契约测试
目标:生产代码净减少行数优先。不要新增替代品,不要为了追求删除行数清理不确定的候选
八、Validation|验证流程
-
编辑源码 / 测试前,关闭正在运行的 Vitest -
遵循 $openclaw-testing;重量级验证走$crabbox规则 -
最小范围执行: node scripts/run-vitest.mjs <path-or-filter>,只跑归属模块及同级测试 -
如果删除源码文本匹配 / 计划断言:执行对应脚本 dry-run 校验真实契约 -
格式化代码 → git diff --check -
用 node scripts/check-changed.mjs --dry-run -- <changed-paths>分类变更,再执行仓库变更门禁 git diff --numstat统计变更,区分生产 / 工具代码 和 测试 / 测试支撑代码 -
审计修改完成,必须执行 $autoreview
九、Landing and continuation|合并与迭代
必须授权后才能提交、推送、创建 PR。使用 $openclaw-pr-maintainer和仓库 pr 脚本流程。一次只合并一个内聚 PR;合并完成后同步 main 分支,重新执行只读扫描,处理下一批高置信度清理项。
十、Handoff|交付输出(审计完成报告)
报告内容清单:
-
根因 + 本次清理的低价值测试分类 -
生产侧代码简化点 -
保留的 “疑似误判” 测试 + 保留理由 -
执行过的定向 / 完整验证用例 -
生产代码变更行数 vs 测试代码变更行数 -
PR 状态、合并状态 -
后续待办事项。

