Harness不是测试工具,而是开发控制面

Harness不是测试工具,而是开发控制面

如果把 Harness 只理解成测试工具,就会错过它最有价值的部分。

测试工具回答的是:这段代码在给定条件下会不会按预期运行。开发 Harness 回答的是:这个任务从被提出到被交付,中间每一步有没有失真、有没有越界、有没有证据、有没有停损点。

测试工具通常包住代码。开发 Harness 包住过程。

一、Test Harness 给我们的启发

一个好的 test harness 会做几件事:

  • 准备被测对象。
  • 构造输入。
  • 替换外部依赖。
  • 控制时间、网络、数据库、文件系统等不稳定因素。
  • 执行动作。
  • 观察输出。
  • 断言结果。
  • 清理环境。

它真正重要的地方,不是“测试”这个词,而是“可控环境”。

没有 Harness 时,代码跑在真实世界里,依赖太多,状态太乱,失败难以复现。有了 Harness,代码被放进一个小型控制舱:输入可知、依赖可知、输出可测。

这件事可以迁移到整个开发过程。

一个需求也是被测对象。它进入开发系统时,天然带着模糊、噪声和缺口。如果不把它放进 Harness,它会在每个阶段变形。最后你得到的不是“解决了问题的代码”,而是“根据一串未验证假设生成的代码”。

二、开发 Harness 控制五件事

开发 Harness 至少有五个控制点。

第一,方向。

方向由 Mode、问题定义、In Scope、Out of Scope 控制。它解决的是“我们到底在做什么”。如果方向没控住,后面所有努力都可能是在加速偏离。

第二,事实。

事实由 Research 控制。它解决的是“我们凭什么这么判断”。开发中最危险的不是未知,而是把未知伪装成已知。Research 要把 Facts、Assumptions、Unknowns 分开。

第三,设计边界。

设计边界由需求、技术设计和实施计划控制。它解决的是“允许怎样改,不允许怎样改”。这里要明确状态流、接口契约、错误态、回滚、监控、验证方式和停损点。

第四,执行。

执行由任务切片、文件边界、测试先行、diff review 控制。它解决的是“怎么保证改动没有偷偷扩大”。AI 参与时尤其重要,因为 AI 很容易把“顺手”变成“已经改了”。

第五,证据。

证据由测试计划、review finding、验收记录、发布报告和复盘控制。它解决的是“我们怎么知道这次真的完成了”。没有证据,完成只是情绪。

三、为什么只靠测试不够

测试很重要,但测试不能替代开发 Harness。

测试通常发生在实现之后。它可以告诉你代码行为是否符合某个预期,但它不一定告诉你预期是否正确。如果问题定义错了,测试越全,越稳定地证明一个错误目标被实现了。

测试通常覆盖代码路径,但不一定覆盖任务边界。一个功能测试通过了,不代表这次没有顺手改坏别的契约。

测试通常验证可观察行为,但不一定验证运维后果。代码能跑,不代表日志足够、指标足够、回滚可行、失败能被发现。

测试通常对付明确输入,但开发失控常常来自隐含输入:一句模糊需求、一个不完整上下文、一段 AI 自行补全的假设。

所以测试是 Harness 的一部分,但不是全部。

更准确地说:

测试 Harness 控制代码运行环境;开发 Harness 控制代码产生过程。

四、一个简单例子

假设任务是:“把文章导出功能优化一下,最近偶尔失败。”

没有开发 Harness 的过程可能是:

  1. 搜索 export。
  2. 看到异常日志。
  3. 猜测是超时。
  4. 增加重试。
  5. 补一个成功导出的测试。
  6. 写结论:已优化。

这个过程很快,但风险很多。

“偶尔失败”到底是什么失败?是生成失败、上传失败、权限失败、任务队列失败、文件过大失败,还是前端轮询超时?

“优化”是什么意思?降低失败率、缩短耗时、改善错误提示、增加重试、增强幂等、补偿历史失败任务,还是增加可观测性?

“增加重试”会不会导致重复导出?会不会重复扣额度?会不会把不可重试错误重试三次?会不会隐藏真正的权限问题?

如果这些都没问,测试成功也只能证明一个很窄的成功路径。

同一个任务放进开发 Harness,过程会变成:

  1. Mode:Hold,只修复和硬化导出失败,不扩展新导出格式。
  2. Research:列出现有导出链路、失败日志、触发条件、相关文件、已有测试。
  3. Problem Framing:确认问题是“导出任务在上传成功但状态写回失败时,会被用户看到为失败且无法恢复”。
  4. Technical Design:设计幂等 key、状态机、错误分类、日志指标、回滚方式。
  5. Implementation Plan:分阶段改状态机、补测试、补指标。
  6. Execution:只改批准文件。
  7. Review:按 happy、nil、empty、error 检查。
  8. Test Plan:记录每条验证命令和证据。
  9. Acceptance:明确剩余风险和是否可发布。

这不是慢。这是把“快但可能错”改成“每一步都知道为什么”。

五、Harness 的几个误区

第一个误区:Harness 等于更多文档。

坏文档确实会拖慢开发。但 Harness 的目标不是写更多字,而是让关键信息不丢。一个好的问题定义可能只有半页,但它能阻止三天偏航。一个好的测试证据台账可能只有一张表,但它能让上线后的复盘有抓手。

第二个误区:Harness 只适合大项目。

小任务更需要轻量 Harness。因为小任务最容易让人觉得“这点事直接改就行”。很多事故不是大项目造成的,而是小改动没有边界、没有测试、没有 review。

第三个误区:AI 可以替代 Harness。

AI 可以帮你生成 Harness 文档,但不能替你决定边界。AI 可以帮你补测试,但不能替你判断哪些风险值得覆盖。AI 可以帮你 review,但如果你没要求它按四路径 review,它很可能给你一段温顺的总结。

第四个误区:Harness 会压制创造力。

真正压制创造力的是混乱。因为混乱会让所有精力都耗在补洞、解释、返工和救火上。Harness 把基本控制面固定住,反而释放了更多思考空间。

六、最小形态

如果一个任务很小,不需要完整文档链,也至少保留最小 Harness:

1
2
3
4
5
6
7
8
9
Mode:
In Scope:
Out of Scope:
Facts:
Assumptions:
Plan:
Validation:
Review Paths:
Residual Risk:

这些字段看起来普通,但它们分别控制不同失控点:

  • Mode 控制变化方向。
  • In Scope 控制本次要做什么。
  • Out of Scope 控制本次不做什么。
  • Facts 控制证据。
  • Assumptions 防止猜测伪装成事实。
  • Plan 控制执行顺序。
  • Validation 控制完成证据。
  • Review Paths 控制边界路径。
  • Residual Risk 控制诚实收尾。

任务变大时,把它展开成完整流程。任务变小时,把它压缩成这几个字段。

Harness 不是仪式,它是可伸缩的控制面。