Documentation
¶
Overview ¶
judge.go —— 事实 + 阈值 + 豁免 → 报告(判据的另一半)。
这里没有任何 I/O:全程是纯函数,故判据的每条分支都能被表驱动用例直接钉住。 把「读日志」与「下判断」分开,是本命令从 awk 改成 Go 的主要理由——awk 版把 判定逻辑与 shell 调用面糊在一起,唯一能测的方式是真的跑一次 make check。
Command pkgcov 是 cover-gate 的**逐包**判据执行体。
为什么判据要落在逐包而不是只看全局 ¶
全局 85.5% 曾同时掩盖着 cmd/docsync 23.6% 与 sandbox 60.0%。全局阈值量的是 「整体没退步」,它对单个包的塌方完全不敏感——大盘涨 1% 就能把一个包从 70 掉到 20 的塌方抵消掉,而报告里只有一行「85.5%,绿」。两个判据判的是两件事,不能互相代替。
为什么从 awk 改成 Go(issue #36) ¶
判据本体此前是一份 80 行的 awk 脚本,`scripts/` 下只有它一个文件,没有任何用例 引用它——检出能力只能靠手工在 /tmp 合成日志验证。而它首版就出过一次真 bug: `coverage: [no statements]` 被 `pct+0` 转成 0%,纯接口包(contract)当场被判红。
假红还能靠「跑一次全量」发现;反方向(提前 exit 0 / 正则漏一类行)则没有任何 信号——make check 照样全绿、照样打印「逐包覆盖率下限 70% ✓」。而本仓纪律是 「门禁自己也要能被检查」「改任何门禁判定逻辑,必须同时给『坏实现会红』的用例」。 awk 做不到:它的判定逻辑与 shell 调用面糊在一起,没法表驱动测。
三条判据(判的是三件事,故都要跑) ¶
- 已计入的包低于下限 ⇒ 红(补该包的用例,别降阈值)
- 豁免包自己达标了 ⇒ 红(豁免失效,必须当天拆除)
- 包没有任何测试文件 ⇒ 红(见下)
第 3 条对应 issue #30:`go test` 对无测试文件的包输出 `? <pkg> [no test files]`, 旧判据跳过这类行——这是**刻意**的(它不是「0% 覆盖」,是「不适用」),但后果是 **没有测试文件的包对逐包下限完全隐形**:新增包若整包不写测试,判据一声不吭。 判据分不出「合理的零测试」与「漏写测试」,那就别假装分得出——要求**显式声明**: 要么补测试,要么在 PKG_NO_TEST_EXEMPT 登记并写清为什么不需要(同样失效即红)。
豁免的纪律 ¶
豁免一旦写成一次性的空条文就会永久留着——半年后没人记得它当初为什么存在, 也没人敢删。故两条豁免都「失效即红」:被豁免的对象自己达标了,就必须当天删掉 那一行。这与 architecture-policy.yaml 的 exceptions 必须写 until 是同一套口径: **豁免可以有,但不能静默,也不能无期限。**
文件切分(按判据的一侧,不按行数) ¶
- parse.go:`go test` 输出 → 事实(形态逐字照抄仪器输出,见该文件头注)
- judge.go:事实 + 阈值 + 豁免 → 报告
- 本文件:命令行装配(`run` 返回退出码而不是自己 os.Exit,用例才够得着)
parse.go —— `go test` 输出的解析面:把仪器输出变成**事实**。
形态必须照抄仪器,不能照抄文档 ¶
本命令第一版把「无测试文件」认成 `? <pkg> [no test files]`——那确实是真形态, 但它只在**不带** `-coverprofile` 时出现。cover-gate 的管道带 `-coverprofile`, 此时同一个包变成一行**无动词**的 `<pkg>\t\tcoverage: 0.0% of statements`。
后果不是「偶尔漏一个包」,而是**零测试包整体失明**:`?` 分支一次都没命中, PKG_NO_TEST_EXEMPT 里那两条豁免于是被判「失效(该包已有测试或不存在)」—— 门禁红在「豁免该拆了」,而真相是它压根没看见那两个包。假红比静默好,但两者 都是判据没对齐现实;而这类偏差只会出现在**真跑过一遍**之后。
故这一面的纪律:形态照抄仪器输出的字节,并写成用例。夹具若比现实好看, 判据就在测一个不存在的世界。
四种行形态(前两条是「有测试」的两种,后两条是「无测试」的两种) ¶
\tok <pkg>\t<time>\tcoverage: 85.5% of statements ⇒ 可测且有覆盖率 \tok <pkg>\t<time>\tcoverage: [no statements] ⇒ 可测但无语句(不适用) \t<pkg>\t\tcoverage: 0.0% of statements ⇒ 无测试文件(-coverprofile 模式) \t? <pkg>\t[no test files] ⇒ 无测试文件(不带 -coverprofile)
不认识的形态怎么办:认识就认,不认识且**长得像**覆盖率事实才红 ¶
制表符开头的行有两种合法来源,不能一刀切成「形态漂移」:
- 带 coverage 列的无动词行 ⇒ 无测试文件(认它,见上表第 3 条);
- 测试自身的日志 / 编译告警的续行(`t.Log` 也可能带制表符)⇒ 又不是覆盖率事实, 必须**放过**——把日志当漂移会让任何一条 `t.Log` 变成门禁的假红。
两条**报错**(而不是跳过)的是:
- `ok` 行没有 `coverage:` 列 ⇒ 调用面少传了 `-cover`。此时每个包都会变成 「无覆盖率数值」而判据一声不吭——这是最危险的一种静默;
- 其余行里出现 `coverage:` 字样 ⇒ 形态漂移(例如新加了别的动词)。
跳过 = 变绿。门禁的失败形态必须是变红;但假红也会训练人忽略门禁,故「长得像」 这个限定是刻意的:判据只在**能证明自己在看覆盖率事实**时才拒绝前进。