SuperAPI AI 工具集

gauntlet

测试与质量

查看项目

更新于 10-31 05:32

技能介绍

Gauntlet 包含两个质量门禁:DRY 门禁和变异(Mutation)门禁。它们与 CRAP 门禁(crap-gate 技能)并列,仅对本次变更触及、且位于与 origin/main 合并基点之后的函数进行评分。本地运行时它们只报告结果;在 CI 中,每个门禁通过仓库变量 DRY_MODE 和 MUTATION_MODE 设置模式,未设置或其他值均为警告模式(仅报告),设置为 block 时:Quality / DRY 作业失败,Required 作业也失败,直到没有未被标记接受的新重复;Quality / Mutation 作业失败,直到没有未被标记接受的存活变异体,Required 作业在两种模式下都不等待它。工具错误、超时、基线失败、错误行、未运行的变异体,或源文件的导入测试数多于本次运行所用测试数时的存活变异体,均不会阻塞。

接受标记:发现可能是有意为之,可在代码旁添加注释说明原因,供审查者同时看到代码和理由。dry-duplicate-ok: <reason> 放在变更函数内部或其正上方的注释行中;放在另一个未变更函数上的标记不算数。mutation-equivalent: <reason> 放在变异体所在行或其正上方的注释行中,覆盖该行所有存活变异体;被杀死的变异体保持被杀。无理由的标记不接受任何内容,只有真实注释才算数,字符串中的标记文本无效。报告会列出每个被接受的发现及其理由。仅在修复措施不适用时才使用标记;仅隐藏缺失测试的标记属于钻门禁空子。

DRY 门禁:运行 make dry-check(或 bun scripts/dry/check.ts --base <ref>)将每个变更函数与 src/ 中所有生产函数比较。评分器为 dryer:丢弃名称、字面量和局部变量,然后对结构的 Jaccard 相似度评分。退出码 0 表示无发现,1 表示有发现,2 表示工具错误。CI 在 Quality / DRY 作业摘要中显示相同报告。发现需要评分不低于 0.82(dryer 默认值)、至少 4 行和 20 个语法节点。只有本次变更造成的配对才是发现:新函数复制另一个函数,或编辑使两个函数匹配。对 main 上已匹配配对的一侧进行编辑是安静的。门禁不跟踪跨文件移动:函数移入另一文件会再次报告其旧配对,应在 PR 中说明,这不是新重复。测试、故事和夹具路径下的文件不计入(遵循 CRAP 门禁的生产文件规则)。修复:如果两个函数必须一起变更(同一规则、格式或协议),将共享形状提取为一个函数并从两处调用;如果它们只是看起来相似且必须分开变更(不同领域恰好共享形状),保留两者并添加 dry-duplicate-ok: 标记说明原因。切勿仅为清除 DRY 发现而合并两个函数,错误的抽象比复制代价更高。

变异门禁:运行 make mutate-check(或 bun scripts/mutate/check.ts --base <ref>)在变更函数中一次制造一个小变异(如 === 改为 !==、> 改为 >=、&& 改为 ||、?? 改为 ||、true 改为 false、0 改为 1 等,遵循 mutator 规则)。对每个变异体,运行导入该文件的 Bun 单元测试。没有测试失败的变异体称为存活,表示没有测试检查该行为。仅支持 Linux 和 macOS(会杀死每个测试的进程组);Windows 上为工具错误。示例输出:mutate-check: 2 survived, 7 killed, 0 uncovered, 0 without a test, 0 not run,并列出文件、测试文件和存活变异体。测试选择:先同目录测试,然后是最多 10 个直接导入该文件的最近其他单元测试。每个测试文件在独立 bun test 进程中运行,使用跟踪文件的私有副本。第一个失败文件杀死变异体。超时(文件自身时间的 10 倍,至少 2 秒)也杀死它。equivalent:在 mutation-equivalent: 标记下的存活变异体。退出码 0 无存活,1 有存活,2 工具错误,3 基线失败(测试文件在无变异体时失败,运行丢弃它,需先修复该测试)。uncovered:使用 --coverage <lcov>(CI 使用 Test / Unit 报告),没有测试运行的行上的变异位点不运行。no-test:没有通过的单元测试导入该文件。not-run:运行达到限制停止(CI:300 个变异体或 15 分钟)。error:运行器在某个变异体上崩溃,报告给出原因,其他变异体仍计数。本地最多 4 个 worker(--workers N)。从小变更开始:触及函数中的每个位点都会运行。修复:编写对变异体失败的测试,断言变异体破坏的行为(边界、另一分支),而不是行;如果没���输入能区分变异体和原始代码,则它是等价的(例如 m[2] 永远不为 "" 时 m[2] ?? "" 和 m[2] || "" 相同),添加 mutation-equivalent: 标记说明原因。切勿仅为杀死变异体而修改生产代码,也切勿添加没有真实断言的测试。CRAP 门禁的反钻空子规则同样适用。