代码0 Bug但业务全跑偏?开发者必看的 Verification 与 Validation 避坑指南

大家好,我是提米哥。今天我们来聊一个让无数开发团队踩过血坑的话题。

几年前,我负责开发一个报表功能。开发过程中,我严格对照需求文档,每一个字段、每一个计算公式、每一个边缘场景都处理得完美无缺。QA 测试也全部绿灯通过。

结果上线第一天,客服就接到了投诉:报表里的数据“技术上完全正确”,但在业务上根本没法用!

为什么?因为需求文档本身写错了——它用的是旧版的财务计算公式,而产品经理在写文档前,根本没去和财务部核对。

这个故事完美诠释了软件工程中两个极易混淆的概念:Verification(核实)Validation(确认)

我们完美地“核实”了代码符合需求文档,却没有人去“确认”需求文档是否符合真实的业务需要。这两件事同样重要,绝不能混为一谈,否则团队会付出极其昂贵的代价。

Verification(核实):我们把东西做对了吗?

Verification 关注的是:软件是否符合规格说明、需求或设计文档?

它是“向内看”的——你只是在检查代码和文档是否一致,而不是检查这东西是不是用户真正想要的。

我们日常说的大部分“测试”,其实都属于 Verification:
– 代码审查(Code Review):检查代码实现是否符合设计文档。
– 单元测试和集成测试:检查代码行为是否符合记录在案的需求。
– 静态分析、代码规范检查(Linting)。
– QA 拿着需求文档,逐条核对验收标准。

Verification 非常擅长抓一种 Bug:“写出来的代码”和“文档要求”之间的差距

但它对另一种 Bug 无能为力:“文档要求”和“真实需求”之间的差距。我开头提到的报表事故,就是 Verification 满分,但 Validation 零分的典型。

Validation(确认):我们做的是正确的东西吗?

Validation 关注的是:软件是否真正解决了现实世界的问题? 无论需求文档是怎么写的。

它是“向外看”的——对照的是现实、用户和真实的业务意图,而不是干巴巴的文档。

Validation 通常长这样:
– 用户验收测试(UAT):让真实用户来用,而不是 QA 对着检查单打勾。
– Beta 测试和灰度发布:收集真实的使用数据。
– 产品和利益相关者评审:对照“要解决的真实问题”来评估,而不是只看任务卡片。
– 观察真实流量涌入时的表现,而不是只测文档里写好的场景。

在 Validation 阶段,“测试全绿”和“可以上线”完全是两码事。一个功能可以被 Verification 到极致,但只要真实用户做了一个需求作者没想到的操作,它依然会瞬间崩溃。

为什么混淆两者代价极其昂贵?

只做 Verification 的团队,往往会过度迷信测试套件。100 个测试全绿让人感觉很有安全感,但如果这 100 个测试都是基于一个有漏洞的需求文档写的,那你只是 “非常完美地开发了一个错误的东西”

Bug 根本不在代码里,而是在上游的需求里。你写再多的单元测试,也抓不到这个 Bug。

这就是为什么“我们的测试覆盖率很高”和“我们的用户很满意”完全是两回事。测试覆盖率衡量的是 Verification,它证明不了 Validation。

Verification 工具箱:它们到底能抓住什么?

我们可以把 Verification 进一步拆解,因为不同的技术能抓住不同类型的错误:

  • 静态核实(Static verification):在代码运行前进行。包括代码审查、设计评审、静态分析、类型检查。它们能抓住结构性问题,比如函数签名不匹配、数据流违规。成本极低,越早发现,修复成本越小。
  • 动态核实(Dynamic verification):运行代码并对比预期行为。包括单测、集成测试、回归测试。这是工程师花时间最多的地方,因为可以快速自动化。但它的局限在于:只能检查代码是否符合“别人写下的预期”。如果需求文档本身不完整,高覆盖率的动态测试也只是在“认真地验证错误的东西”。
  • 形式化核实(Formal verification):用数学方法证明程序正确。通常只用于航天、医疗设备等 Bug 会导致灾难的领域。大部分团队用不到,但你要知道:即使数学上证明完美的程序,也只是相对于“规格说明”完美。如果规格说明错了,形式化核实只会完美地证明一个错误。

总结规律:从静态审查到形式化证明,Verification 越来越严谨,但没有任何一种 Verification 能告诉你需求文档是否符合现实。这个鸿沟只能靠 Validation 来填补。

Validation 方法:为什么它很难被自动化?

Validation 的技术看起来完全不同,因为它们要对照的是比文档模糊得多的“现实”:

  • 用户验收测试(UAT):把软件交给真实用户或业务专家,问他们“这能满足你的需求吗?” UAT 经常能暴露出 Verification 阶段看不到的需求漏洞,因为测试者不是在走流程,而是在尝试完成真实任务。
  • Beta 计划和灰度发布:将测试扩大到真实的大规模使用场景。5 个友好的内测用户通过的 UAT,在面对海量真实用户的“奇葩”操作时,依然可能崩溃。
  • 生产监控和事故分析:永不停止的 Validation。每一个 Bug 报告、每一张困惑的客服工单、每一个意料之外的使用模式,都是系统是否满足真实需求的最诚实信号。
  • 领域和利益相关者评审:回去找真正懂业务的人,问他们“这解决了你们的实际问题吗?” 这是最不“技术”、也最容易被跳过的 Validation,但它往往能在代码写下之前,就避免我开头提到的报表惨剧。

共同点:Validation 很难完全自动化,因为它面对的是不断变化的真实世界,而不是固定的文档。你可以自动化回归测试,但你无法完全自动化“人类觉得这东西好不好用”。

提米哥的实战建议:两者该如何配合?

  • Verification 应该靠近代码:越早、越自动化越好。因为它对照的是明确且稳定的东西(文档、契约)。这是自动化测试套件发挥价值的地方:快速、可重复地检查代码是否符合约定。
  • Validation 必须接触现实:它需要真实用户、真实流量、没人想到的边缘场景。这也是很多团队投资不足的地方,因为它很难自动化,也很难有一个“绿灯”告诉你“绝对做对了”。你只能从真实使用中持续获取反馈。

在软件工程中,Verification 和 Validation 绝不能互相替代。

一个 Verification 极强但 Validation 极弱的团队,会交付一个“测试完美但没人用”的产品;
一个 Validation 极强但 Verification 拉胯的团队,会交付一个“点子很好但 Bug 满天飞”的半成品。

最健康的团队,会把它们当成两个独立的问题,在整个开发周期中持续追问。

下次当你开发的功能测试全绿,但用户却一脸懵逼时,不妨停下来想想:到底是哪一步失败了?通常,真不是测试的锅。

直达网址:https://keploy.io/blog/community/verification-vs-validation

类似文章