“四十项测试”首先是一个清单数量,不是可靠性分数。
当前三份测试文件确实全部通过,共分成三组:14 项历史黑盒案例、9 项假设相似性检查、17 项算法与数据不变量。这个拆分比总数更有信息,因为三组使用的 oracle 不同,也留下不同空白。
四十项怎样组成
| 组别 | 数量 | 已覆盖的对象 | 不能由它推出 |
|---|---|---|---|
| 历史黑盒案例 | 14 | 阶段输入、退出码、弱 Kill、证据缺失、阶段跳转 | 新增即时规则入口全部正确 |
| 相似性检查 | 9 | 相同与不同描述、阈值、状态过滤、局部算法行为 | 真实任务的语义相关性正确 |
| 不变量 | 17 | 概率归一、似然比顺序、吸收态、时间衰减、文本归一化 | 生成器覆盖了最危险业务状态 |
历史案例里同时有正向与负向输入。例如,观察阶段少于两条假设、干预阶段缺少预测、收敛阶段缺少直接证据,以及从 OBSERVE 跳过 INTERVENE 直接收敛,都有稳定的预期退出码。
相似性组检查相同字符串、明显不同字符串、阈值变化和已结束状态过滤。不变量组使用性质测试反复生成输入,检查活跃假设概率范围、killed / confirmed 吸收态、stale 处理、关键词拆分和签名一致性。
这些是测试代码能够证明的覆盖类型,不是测试曾经挡住过某次真实回归的记录。
每组测试使用不同 oracle
历史黑盒案例的 oracle 是退出码与阶段契约。相似性检查使用固定样本上的分数、克隆判断和过滤结果。性质测试的 oracle 则是一组对生成输入都应成立的不变量。
三种 oracle 不能直接相加成一个“可靠性分数”:
- 退出码稳定,不代表数据库写入正确;
- 固定样本相似,不代表真实任务根因相同;
- 随机运行一百次,不代表覆盖了一百种业务状态;
- 概率始终在定义域内,不代表假设本身有业务价值。
测试数量应该被读成证据地图:哪里已有观察,哪里仍是空白。
一个未被四十项发现的控制流缺口
即时 IDE 规则中有一段弱 Kill 条件检查:前置分支只要发现 Kill: 就直接 continue,后面的弱值判断因此可能不可达。
历史黑盒组确实包含“弱 Kill 条件应失败”的案例,但它覆盖的是另一条完整验证路径。40 项全部通过,仍然没有证明新增的即时入口执行了同样语义。
这不是测试无效,而是 subject 不同。旧入口的回归测试不能自动覆盖新入口的控制流。
这个具体缺口在《一条被 continue 绕过的 Kill 条件检查》中展开。它也给测试账本增加了一个必要字段:每条测试究竟绑定哪个入口。
每项测试需要一条证据记录
test_id
subject
entrypoint
oracle
failure_mode
explicit_boundary
fixture_source
last_red_evidence
其中:
subject是被检查的对象;entrypoint指明测试经过哪个公开入口;oracle描述什么结果被视为正确;failure_mode说明它能发现哪类错误;explicit_boundary写出明确不覆盖什么;fixture_source区分固定案例、生成器与人工样本;last_red_evidence保留最近一次真实失败与修复记录。
前六项可以从现有测试代码整理。最后一项需要真实历史,不能根据“现在是绿的”反推。
这张账本还能识别重复证据:多项测试如果拥有相同 subject、entrypoint、oracle 和 failure mode,更可能是在加密同一区域,而不是扩展风险覆盖。
目前必须停止的结论
现有材料不足以声称:
- 四十项覆盖了完整验证链;
- 测试曾经阻止某次真实回归;
- 性质生成器覆盖了足够多危险状态;
- 当前测试降低了多少缺陷;
- 执行速度适合每次修改后运行;
- 即时规则、自动验证、数据库迁移和检索质量都已经被覆盖。
能够成立的判断是:三组测试保护了部分历史契约、局部相似性行为和明确不变量;这次控制流审查同时证明,测试地图仍有未覆盖入口。
从测试清单到工程历史还缺一列
下一轮真正需要的不是第 41 个数量,而是至少一条真实红灯记录:什么修改让哪项测试失败,oracle 捕获了哪个风险,修复差异是什么,重新通过后又能证明到哪里。
在这条记录出现以前,四十项测试是一组可核查的基础防线,不是一份已经完成的可靠性证明。测试账本的作用,就是让两句话可以同时成立:现有覆盖值得保留,未覆盖风险仍然必须可见。