---
order: 14
date: 2026-08-05
summary: ——没红过的测试不可信
---

# 一张有答案的考卷

**——没红过的测试不可信**

工程可以靠单元测试验证失败，因为每条断言背后都预设着标准答案；法律却没有严格的对与错，没有什么标准答案。所以法律能自动化的检查，往往全是结构性的，而不是结果性的。顺着这个推理走，很容易得出一个结论：带答案的测试与法律无缘。然而实际上，我们还是可以考虑用近似和拟制的方法来做——先来看工程上是怎么做测试的。

## 测试的解剖

一条测试的标准结构是三段：**布置—执行—断言**。布置：把输入和环境摆好；执行：调用被测的东西；断言：拿实际输出和期望比对。行为驱动的写法换了个说法——Given（给定什么前提）、When（发生什么动作）、Then（应当看到什么）——骨架是同一副。两条纪律贯穿始终：一条测试只问一个问题，失败时的报错要能直接告诉人坏在哪。

用例从哪里来？先写一条正常路径——最典型的输入、最该对的输出。然后是**边界**：空的、零个的、恰好一个的、恰好装满的、超出一个的——缺陷扎堆的地方从来不在腹地，在边境线上。然后是**等价类**：输入有无穷多种，但程序应当同样对待的输入属于同一类，每类取一个代表就够——测试的艺术一半在于划类划得准。最后是**错误路径**：非法输入进来，程序应当明确拒绝，而不是沉默地吞下去算出个东西——“报错也是一种正确行为”，而且是最容易漏测的一种。

还有一条经验法则，重要到值得单列：**没红过的测试不可信。** 一条从写出来就一直绿的测试，可能断言写错了，可能测的是替身，可能根本没跑到目标代码——它的绿没有含义。所以测试驱动开发坚持先写测试看它红：红灯是测试自己的资格考试，证明它真的抓得住它声称要抓的东西。

## 答案从哪里来

三段式里最难的从来是最后一段：断言要有期望值，期望值就是答案。按答案的来源摆开，常用方法排成一道谱——对答案的要求逐级降低，换来的覆盖面逐级扩大。

**手算的答案。** 样例测试：`sort([3,1,2])` 应当等于 `[1,2,3]`，期望值是人算出来的。绝大多数测试属于这一类，它的极限也明显——人算得动的输入才测得了。

**存档的答案。** 输出庞大到手算不动时——一张渲染出的报表、一份生成的文书——办法是把某次人工确认过的输出存档，此后每次运行和存档 diff，不同即红。这叫金标准测试或快照测试。它的风险是把错误也一并存进档：**“和上次一样”不等于“对”**，档案本身要定期有人重新过目。

**对拍的答案。** 两个独立实现互为答案：一个慢而显然正确的参照实现，对一个快而复杂的优化实现，随机灌同样的输入，断言输出一致。这叫差分测试。没有谁手里有真理，但两个独立来源的一致是强证据，不一致是明确的报警。

**用性质代替答案。** 不知道某个输入的期望输出，也可以断言输出必须满足的不变量：排序的结果必须有序、必须是输入的重排——两条性质圈住了“正确”，一个具体答案都不用给。然后随机生成成千上万个输入去轰它。性质测试的覆盖面是样例测试的几个数量级之上，代价是想出好性质比想出好样例难。

**不要答案。** 谱的末端是模糊测试：灌海量畸形输入，只断言一件事——不崩溃。这是最弱的断言，却抓得住谁也想不到去测的角落。

## 给合同审查出题

现在回到法律。法律没有天然的 oracle，这个结论不必收回；但工程对此的回应不是认命，是**拟制**。法律人对这门手艺不该陌生：宣告死亡、视为送达——明知未必为真，却郑重当真来用的制度装置。给法律场景设置起标准答案作用的东西，走的是同一条路：**答案不是找到的，是立起来的**——要紧的只是记住它是拟制的，并看清它在哪一段撑得住。

上一篇结尾已经这么做过一次：把已生效的判决拟制为标准答案，测推理机器像不像法官。本篇做第二次，场景选在合同审查——选这里，是因为拟制在这里成色最足，有两个原因。

第一，问题形态合适。合同审查回答的不是“该判谁赢”，是“**这份文本里有哪些坑**”——缺陷识别，不是价值裁断。资深律师面对一条无上限的连带责任条款、一项单方任意解除权、一处约到对方主场的管辖，结论几乎不会分歧。专家在这类问题上的一致性，远高于他们在裁判结果上的一致性——一致性够高，金标准就立得住。

第二，真题充沛。合同是法律实务里流量最大的文本：每家律所、每个法务部手里都躺着大量审过的合同——原文、批注、来回修改的版本俱在。这不是需要凭空出题的场景，是真题堆到天花板、只欠把答案立起来的场景。

于是考卷的做法就清楚了：真实合同脱敏入库，由资深律师标注金标准——每处问题的位置、性质、严重级别。标注的对象就是实务里最熟的那些坑：无上限连带担保、单方任意解除权、违约金畸高、管辖异地、付款节点与交付义务错位、争议解决条款自相矛盾、定义条款与正文冲突……标注有分歧的条款经合议定稿，定不下来的剔除出卷——考卷只收专家收敛的题。历史批注是现成的起点：当年审查时标了什么、最终改成了什么，本身就是一份等待整理的答案底稿。

评分规则要认真设计，因为合同审查的错误成本是**不对称**的：漏掉一个致命条款，和多标三条无关痛痒的“风险提示”，不是同一量级的错。所以缺陷分级——致命、重要、提示——查全率按级加权，漏检致命项重罚；同时冤枉正常条款也要扣分：满篇皆红的审查报告等于没有审查，它把发现的成本原样转嫁回了读它的人。

## 一卷两用

这张考卷最值钱的地方，是同一张卷子测得了两样东西。

**测规则。** 审查清单——律所代代相传的那种 checklist——本身是一套规则，而规则的有效性从来靠资历背书：“这是某某合伙人定的版本。”现在可以量：这套清单对这张考卷抓回多少、漏掉的集中在哪类缺陷。修订清单之后重跑同一张卷，就是规则的回归测试——改进有数字，退步也藏不住。清单从祖传秘方变成可以迭代的工程对象。

**测模型。** 换一个模型、改一版提示词、升一次版本，同一张卷跑下去，能力从形容词变成数字：“新版本加权查全率从八成二到九成一，致命项漏检清零”和“感觉更聪明了”，是两个时代的说法。模型选型和提示词迭代，第一次有了可比的依据；版本升级也第一次有了硬性门槛——新版本在考卷上不得低于旧版本，否则不上线。

两个用途还可以相乘：同一张卷，横轴换模型，纵轴换规则，哪一格的组合最强，一目了然。

## 考卷的边界

最后照例说清楚这办法兜不住什么，否则又是一门新迷信。

**考卷会被背熟。** 指标一旦成为目标，就不再是好指标。题库如果进了训练语料，或者提示词被对着题库反复调优，分数就开始失真——测出的不再是能力，是记忆。对策和考试制度一样古老：保留一套不公开的盲卷，题库定期轮换，新的缺陷类型持续入库。

**答案是判断的存档，不是真理。** 金标准由专家标注，它继承标注者的立场和盲区。它测得出“漏没漏”，测不出“该不该改”——一条风险要不要为了促成交易吃下去，是生意判断，不在考卷的射程内，也不该在。

**这条路不止一张考卷。** 合同审查不是法律里天然长着答案的例外——这里的答案是专家合议拟制出来的，同样的手艺可以搬去别处。判决拟制为标准答案是一次，这张考卷是一次；往后每找到一处专家足够收敛的场景，就能再立一套。法律推理的大部分依旧在无 oracle 的旷野里，但旷野不是判词，是待办清单：凡是拟制立得起来的地方，先出卷，再上岗。

因为道理在两个行当里是同一条：**没红过的测试不可信，没考过卷的审查者也一样——你不知道它的绿灯，究竟是本事，还是没遇上事。**
