一个大输入触发了 bug。几十行、几百行,甚至更大。工程师开始手工删:删一段,跑一次;删错了,bug 没了;删对了,线索才露一点。
Laurence Tratt 写的 test-case reducer,盯的就是这个老问题。它让机器替人删输入,把一个大而乱的失败样本,压成尽可能小的可复现样本。原文提到,95%-99% 的缩减并不少见。
反常点在这里:这种工具通常不靠聪明。它不理解程序,不理解 bug,也不懂业务语义。它只问一个硬问题:删完以后,目标问题还在不在?
reducer 到底在做什么
test-case reducer 需要三样东西。
| 要素 | 作用 | 写错的后果 |
|---|---|---|
| 程序 | 被调试或被验证的对象 | 没有稳定目标,压缩无从谈起 |
| 输入 | 触发问题的大样本 | 样本不复现,结果会失真 |
| interestingness test | 判断缩小后的输入是否仍触发目标问题 | 条件太松,会过度缩减;条件太严,压不下去 |
这里的 interesting,不是“有意思”。它的意思是:这个输入仍然触发你关心的失败。比如仍然崩溃,仍然输出错误结果,仍然让两个配置跑出不同结果。
reducer 会不断尝试删掉输入的一部分。删完后,它把候选输入交给 interestingness test。测试通过,就保留更小版本;不通过,就换一种删法。
Shrink Ray 的例子说明了这个过程的力度:有的 C 输入先压掉 60%;有的真实缩减过程先找到关键删除点,压掉 90%,最后到 99%。bug 原本埋在噪声里,压完以后,剩下的才像线索。
这对经常处理复杂 bug 的工程师很直接:别先急着读完整大样本。先问自己能不能写一个脚本,稳定判断“问题还在”。只要能写出来,手工删输入这件事就应该交给机器。
它强在不懂,也败在测试写得烂
很多人会误会 reducer,以为它靠语义理解。原文强调的恰好相反:它的强大来自“不理解语义”。
它不需要知道 C 语言,不需要知道业务规则,也不需要知道为什么错。只要 interestingness test 能判断目标问题还在,它就能继续往下削。
这有点像“庖丁解牛”,但刀并不懂牛。刀只认一个反馈:这一刀下去,目标还在不在。落回调试现场,这比很多“智能分析”更实用,因为它把判断标准固定住了。
风险也在同一个地方。
interestingness test 写得太松,reducer 会 over-reduction。最糟糕时,它可能接受空输入。原文提到,Shrink Ray 还会专门检查 interestingness test 是否把空输入也当成 interesting,因为这种错误并不少见。
那个 FAST=0 和 FAST=1 输出不同的例子,也不能只检查“两边不同”。还要确认慢版本输出的是预期值。否则 reducer 可能保留一个无关差异,把你带到另一条岔路。
速度是另一个硬约束。reducer 可能每秒运行数百次测试,中等规模输入也可能产生数十万次尝试。interestingness test 慢一点,总耗时就会被放大很多倍。
非确定性错误、偶发失败、超时设置不当,也会污染结果。reducer 不是调试神药。它只是把战场缩小,前提是你的判定条件足够稳、足够快、足够准。
真正被低估的是调试自动化
我更在意的不是某个 reducer 工具,而是它暴露出的工程习惯。
很多团队谈研发效率,喜欢上更大的 IDE、更智能的 AI、更复杂的观测平台。可一到具体调试,还是人肉删输入,靠直觉猜路径,靠资深工程师熬夜看日志。
问题不一定是工具少,而是复现条件没有机器化。
对工程师来说,下一步动作很具体:遇到大输入 bug,先写一个最小判定脚本。它可以很朴素,只要能稳定回答“目标问题是否还在”。然后再考虑把 reducer 接进流程。
对技术负责人来说,重点也不是立刻采购一套新平台。更该检查团队有没有把复杂 bug 的复现条件沉淀成脚本、测试或 CI 任务。没有这个动作,调试自动化就只是口号。
这里有一个现实对比:
| 做法 | 短期成本 | 长期收益 | 主要限制 |
|---|---|---|---|
| 手工删输入 | 低 | 依赖个人经验,难复用 | 慢,容易漏,难交接 |
| 写 interestingness test 后用 reducer | 中 | 可反复运行,可压缩样本,可复盘 | 测试必须稳定、快速、严格 |
我不太买账的是那种“工具会自动理解问题”的期待。至少在这类场景里,更可靠的路线反而更朴素:人把判断条件写清楚,机器负责重复劳动。
这也是接下来最该观察的变量:团队是否愿意把 bug 的复现条件变成可运行资产。不是文档里一句“复现步骤”,而是一段能跑、能判定、能被 reducer 反复调用的测试。
大输入是迷雾。好的 interestingness test,是灯。灯不负责破案,但它能让你别在雾里乱砍。
