
文章目录
- [软件开发模型系列(二):V 模型 ------ 让测试不再是事后诸葛亮](#软件开发模型系列(二):V 模型 —— 让测试不再是事后诸葛亮)
- [1、什么是 V 模型](#1、什么是 V 模型)
- [2、V 模型解决了什么问题](#2、V 模型解决了什么问题)
- [3、V 模型的历史渊源](#3、V 模型的历史渊源)
- [4、V 模型的核心价值:可追溯性](#4、V 模型的核心价值:可追溯性)
- [5、V 模型中验证与确认的区别](#5、V 模型中验证与确认的区别)
- [6、V 模型的优点](#6、V 模型的优点)
- [7、V 模型的局限](#7、V 模型的局限)
- [8、V 模型 vs 瀑布模型](#8、V 模型 vs 瀑布模型)
- [9、AI 时代的思考](#9、AI 时代的思考)
- 10、本篇要点速记
- [附录:从"测试"到"证据链"------对 V 模型更深一层的理解](#附录:从"测试"到"证据链"——对 V 模型更深一层的理解)
-
- 第三层:架构验证(很多人开始模糊)
- 第四层:需求验证(最容易误解)
- [高级别 Validation 长什么样?](#高级别 Validation 长什么样?)
- [V-Model 右边,其实不是 Test](#V-Model 右边,其实不是 Test)
- [AI Agent 时代,这个思想反而越来越重要](#AI Agent 时代,这个思想反而越来越重要)
- 最本质的一句话
软件开发模型系列(二):V 模型 ------ 让测试不再是事后诸葛亮
瀑布模型把开发流程理顺了,但它有一个致命问题:测试被放在最后。等发现 Bug 的时候,设计文档都归档了,程序员都转岗了。V 模型正是为了解决这个问题而生。
1、什么是 V 模型
V 模型(V-Model) 可以理解为瀑布模型的"对称升级版"。它的核心创新是:每一个开发阶段,都对应一个测试阶段。
想象字母 "V" 的形状:
#mermaid-svg-rOSggMyLoyFRjxok{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-rOSggMyLoyFRjxok .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-rOSggMyLoyFRjxok .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-rOSggMyLoyFRjxok .error-icon{fill:#552222;}#mermaid-svg-rOSggMyLoyFRjxok .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rOSggMyLoyFRjxok .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-rOSggMyLoyFRjxok .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rOSggMyLoyFRjxok .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rOSggMyLoyFRjxok .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-rOSggMyLoyFRjxok .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rOSggMyLoyFRjxok .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rOSggMyLoyFRjxok .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rOSggMyLoyFRjxok .marker.cross{stroke:#333333;}#mermaid-svg-rOSggMyLoyFRjxok svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rOSggMyLoyFRjxok p{margin:0;}#mermaid-svg-rOSggMyLoyFRjxok .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-rOSggMyLoyFRjxok .cluster-label text{fill:#333;}#mermaid-svg-rOSggMyLoyFRjxok .cluster-label span{color:#333;}#mermaid-svg-rOSggMyLoyFRjxok .cluster-label span p{background-color:transparent;}#mermaid-svg-rOSggMyLoyFRjxok .label text,#mermaid-svg-rOSggMyLoyFRjxok span{fill:#333;color:#333;}#mermaid-svg-rOSggMyLoyFRjxok .node rect,#mermaid-svg-rOSggMyLoyFRjxok .node circle,#mermaid-svg-rOSggMyLoyFRjxok .node ellipse,#mermaid-svg-rOSggMyLoyFRjxok .node polygon,#mermaid-svg-rOSggMyLoyFRjxok .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-rOSggMyLoyFRjxok .rough-node .label text,#mermaid-svg-rOSggMyLoyFRjxok .node .label text,#mermaid-svg-rOSggMyLoyFRjxok .image-shape .label,#mermaid-svg-rOSggMyLoyFRjxok .icon-shape .label{text-anchor:middle;}#mermaid-svg-rOSggMyLoyFRjxok .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-rOSggMyLoyFRjxok .rough-node .label,#mermaid-svg-rOSggMyLoyFRjxok .node .label,#mermaid-svg-rOSggMyLoyFRjxok .image-shape .label,#mermaid-svg-rOSggMyLoyFRjxok .icon-shape .label{text-align:center;}#mermaid-svg-rOSggMyLoyFRjxok .node.clickable{cursor:pointer;}#mermaid-svg-rOSggMyLoyFRjxok .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-rOSggMyLoyFRjxok .arrowheadPath{fill:#333333;}#mermaid-svg-rOSggMyLoyFRjxok .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-rOSggMyLoyFRjxok .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-rOSggMyLoyFRjxok .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rOSggMyLoyFRjxok .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-rOSggMyLoyFRjxok .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rOSggMyLoyFRjxok .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-rOSggMyLoyFRjxok .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-rOSggMyLoyFRjxok .cluster text{fill:#333;}#mermaid-svg-rOSggMyLoyFRjxok .cluster span{color:#333;}#mermaid-svg-rOSggMyLoyFRjxok div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-rOSggMyLoyFRjxok .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-rOSggMyLoyFRjxok rect.text{fill:none;stroke-width:0;}#mermaid-svg-rOSggMyLoyFRjxok .icon-shape,#mermaid-svg-rOSggMyLoyFRjxok .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rOSggMyLoyFRjxok .icon-shape p,#mermaid-svg-rOSggMyLoyFRjxok .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-rOSggMyLoyFRjxok .icon-shape .label rect,#mermaid-svg-rOSggMyLoyFRjxok .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rOSggMyLoyFRjxok .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-rOSggMyLoyFRjxok .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-rOSggMyLoyFRjxok :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-rOSggMyLoyFRjxok .stage>*{fill:#dbeafe!important;stroke:#2563eb!important;stroke-width:1px!important;color:#1e3a8a!important;}#mermaid-svg-rOSggMyLoyFRjxok .stage span{fill:#dbeafe!important;stroke:#2563eb!important;stroke-width:1px!important;color:#1e3a8a!important;}#mermaid-svg-rOSggMyLoyFRjxok .stage tspan{fill:#1e3a8a!important;}#mermaid-svg-rOSggMyLoyFRjxok .test>*{fill:#dcfce7!important;stroke:#16a34a!important;stroke-width:1px!important;color:#14532b!important;}#mermaid-svg-rOSggMyLoyFRjxok .test span{fill:#dcfce7!important;stroke:#16a34a!important;stroke-width:1px!important;color:#14532b!important;}#mermaid-svg-rOSggMyLoyFRjxok .test tspan{fill:#14532b!important;} 测试活动(自下而上验证)
开发活动(自上而下细化)
验证
验证
验证
需求分析
系统设计
详细设计
编码实现
单元测试
集成测试
系统测试
验收测试
V 的左半边 是开发活动(自上而下逐步细化),右半边是测试活动(自下而上逐步集成验证)。左右两侧的水平连线表示"这个开发阶段需要被对应的测试阶段所验证"。

左边:不断拆需求。
右边:不断验证需求。
真正的思想:每一种设计,都必须有一种对应的测试。
Every Design Must Have A Verification.
2、V 模型解决了什么问题
瀑布模型的一个经典悲剧场景:
text
需求分析 → 系统设计 → 编码 → 编码 → 编码 → 编码 → 编码 →
...6 个月后...
→ 测试
测试人员:"登录功能在 Safari 浏览器下完全打不开。"
开发人员:"......设计文档里没说要做跨浏览器兼容。"
产品经理:"用户说了要用 Safari 啊。"
开发人员:"需求文档里没写。"
问题出在哪?测试的"验证标准"在开发阶段没有提前定义。
V 模型的做法是:
#mermaid-svg-x34RgwSlivvaSRNE{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-x34RgwSlivvaSRNE .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-x34RgwSlivvaSRNE .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-x34RgwSlivvaSRNE .error-icon{fill:#552222;}#mermaid-svg-x34RgwSlivvaSRNE .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-x34RgwSlivvaSRNE .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-x34RgwSlivvaSRNE .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-x34RgwSlivvaSRNE .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-x34RgwSlivvaSRNE .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-x34RgwSlivvaSRNE .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-x34RgwSlivvaSRNE .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-x34RgwSlivvaSRNE .marker{fill:#333333;stroke:#333333;}#mermaid-svg-x34RgwSlivvaSRNE .marker.cross{stroke:#333333;}#mermaid-svg-x34RgwSlivvaSRNE svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-x34RgwSlivvaSRNE p{margin:0;}#mermaid-svg-x34RgwSlivvaSRNE .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-x34RgwSlivvaSRNE .cluster-label text{fill:#333;}#mermaid-svg-x34RgwSlivvaSRNE .cluster-label span{color:#333;}#mermaid-svg-x34RgwSlivvaSRNE .cluster-label span p{background-color:transparent;}#mermaid-svg-x34RgwSlivvaSRNE .label text,#mermaid-svg-x34RgwSlivvaSRNE span{fill:#333;color:#333;}#mermaid-svg-x34RgwSlivvaSRNE .node rect,#mermaid-svg-x34RgwSlivvaSRNE .node circle,#mermaid-svg-x34RgwSlivvaSRNE .node ellipse,#mermaid-svg-x34RgwSlivvaSRNE .node polygon,#mermaid-svg-x34RgwSlivvaSRNE .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-x34RgwSlivvaSRNE .rough-node .label text,#mermaid-svg-x34RgwSlivvaSRNE .node .label text,#mermaid-svg-x34RgwSlivvaSRNE .image-shape .label,#mermaid-svg-x34RgwSlivvaSRNE .icon-shape .label{text-anchor:middle;}#mermaid-svg-x34RgwSlivvaSRNE .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-x34RgwSlivvaSRNE .rough-node .label,#mermaid-svg-x34RgwSlivvaSRNE .node .label,#mermaid-svg-x34RgwSlivvaSRNE .image-shape .label,#mermaid-svg-x34RgwSlivvaSRNE .icon-shape .label{text-align:center;}#mermaid-svg-x34RgwSlivvaSRNE .node.clickable{cursor:pointer;}#mermaid-svg-x34RgwSlivvaSRNE .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-x34RgwSlivvaSRNE .arrowheadPath{fill:#333333;}#mermaid-svg-x34RgwSlivvaSRNE .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-x34RgwSlivvaSRNE .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-x34RgwSlivvaSRNE .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-x34RgwSlivvaSRNE .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-x34RgwSlivvaSRNE .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-x34RgwSlivvaSRNE .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-x34RgwSlivvaSRNE .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-x34RgwSlivvaSRNE .cluster text{fill:#333;}#mermaid-svg-x34RgwSlivvaSRNE .cluster span{color:#333;}#mermaid-svg-x34RgwSlivvaSRNE div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-x34RgwSlivvaSRNE .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-x34RgwSlivvaSRNE rect.text{fill:none;stroke-width:0;}#mermaid-svg-x34RgwSlivvaSRNE .icon-shape,#mermaid-svg-x34RgwSlivvaSRNE .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-x34RgwSlivvaSRNE .icon-shape p,#mermaid-svg-x34RgwSlivvaSRNE .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-x34RgwSlivvaSRNE .icon-shape .label rect,#mermaid-svg-x34RgwSlivvaSRNE .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-x34RgwSlivvaSRNE .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-x34RgwSlivvaSRNE .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-x34RgwSlivvaSRNE :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-x34RgwSlivvaSRNE .stage>*{fill:#dbeafe!important;stroke:#2563eb!important;stroke-width:1px!important;color:#1e3a8a!important;}#mermaid-svg-x34RgwSlivvaSRNE .stage span{fill:#dbeafe!important;stroke:#2563eb!important;stroke-width:1px!important;color:#1e3a8a!important;}#mermaid-svg-x34RgwSlivvaSRNE .stage tspan{fill:#1e3a8a!important;}#mermaid-svg-x34RgwSlivvaSRNE .test>*{fill:#dcfce7!important;stroke:#16a34a!important;stroke-width:1px!important;color:#14532b!important;}#mermaid-svg-x34RgwSlivvaSRNE .test span{fill:#dcfce7!important;stroke:#16a34a!important;stroke-width:1px!important;color:#14532b!important;}#mermaid-svg-x34RgwSlivvaSRNE .test tspan{fill:#14532b!important;} 同时写好
同时写好
同时写好
同时写好
写需求
验收测试用例
怎么才算需求被满足
做设计
系统测试用例
怎么验证设计正确
详细设计
集成测试用例
模块间怎么联调
写代码
单元测试用例
这个函数对不对
这样就不会等到最后才发现"需求根本没被理解对"。
3、V 模型的历史渊源
V 模型最早起源于德国联邦政府的军用和政务软件开发标准,后来被广泛应用于对安全性有严格要求的行业。
需要注意的是,IEC 62304(医疗设备软件生命周期标准)并没有强制要求使用 V 模型------标准附录中的 V 形图只是作为参考示意。但 V 模型的思想(开发与验证的对应关系、双向可追溯性)已经深深嵌入了各类安全关键领域的标准之中:
| 行业 | 相关标准 |
|---|---|
| 航空 | DO-178C(机载软件) |
| 汽车 | ISO 26262(功能安全) |
| 医疗 | IEC 62304(医疗设备软件) |
| 铁路 | EN 50128(铁路控制和防护) |
| 核电 | IEC 61513 / IEC 60880(核电仪控与安全级软件) |
注:IEC 61508 是与行业无关的"功能安全基础(母)标准",上表中的 ISO 26262(汽车)、EN 50128(铁路)等都是从它派生出来的------它本身并不专属于某个行业。
4、V 模型的核心价值:可追溯性
V 模型最值得学习的不是那个 "V" 的形状,而是双向可追溯性(Bidirectional Traceability):
#mermaid-svg-BCdrqQTmfw4fTSU7{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-BCdrqQTmfw4fTSU7 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-BCdrqQTmfw4fTSU7 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-BCdrqQTmfw4fTSU7 .error-icon{fill:#552222;}#mermaid-svg-BCdrqQTmfw4fTSU7 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-BCdrqQTmfw4fTSU7 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-BCdrqQTmfw4fTSU7 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-BCdrqQTmfw4fTSU7 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-BCdrqQTmfw4fTSU7 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-BCdrqQTmfw4fTSU7 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-BCdrqQTmfw4fTSU7 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-BCdrqQTmfw4fTSU7 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-BCdrqQTmfw4fTSU7 .marker.cross{stroke:#333333;}#mermaid-svg-BCdrqQTmfw4fTSU7 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-BCdrqQTmfw4fTSU7 p{margin:0;}#mermaid-svg-BCdrqQTmfw4fTSU7 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-BCdrqQTmfw4fTSU7 .cluster-label text{fill:#333;}#mermaid-svg-BCdrqQTmfw4fTSU7 .cluster-label span{color:#333;}#mermaid-svg-BCdrqQTmfw4fTSU7 .cluster-label span p{background-color:transparent;}#mermaid-svg-BCdrqQTmfw4fTSU7 .label text,#mermaid-svg-BCdrqQTmfw4fTSU7 span{fill:#333;color:#333;}#mermaid-svg-BCdrqQTmfw4fTSU7 .node rect,#mermaid-svg-BCdrqQTmfw4fTSU7 .node circle,#mermaid-svg-BCdrqQTmfw4fTSU7 .node ellipse,#mermaid-svg-BCdrqQTmfw4fTSU7 .node polygon,#mermaid-svg-BCdrqQTmfw4fTSU7 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-BCdrqQTmfw4fTSU7 .rough-node .label text,#mermaid-svg-BCdrqQTmfw4fTSU7 .node .label text,#mermaid-svg-BCdrqQTmfw4fTSU7 .image-shape .label,#mermaid-svg-BCdrqQTmfw4fTSU7 .icon-shape .label{text-anchor:middle;}#mermaid-svg-BCdrqQTmfw4fTSU7 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-BCdrqQTmfw4fTSU7 .rough-node .label,#mermaid-svg-BCdrqQTmfw4fTSU7 .node .label,#mermaid-svg-BCdrqQTmfw4fTSU7 .image-shape .label,#mermaid-svg-BCdrqQTmfw4fTSU7 .icon-shape .label{text-align:center;}#mermaid-svg-BCdrqQTmfw4fTSU7 .node.clickable{cursor:pointer;}#mermaid-svg-BCdrqQTmfw4fTSU7 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-BCdrqQTmfw4fTSU7 .arrowheadPath{fill:#333333;}#mermaid-svg-BCdrqQTmfw4fTSU7 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-BCdrqQTmfw4fTSU7 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-BCdrqQTmfw4fTSU7 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BCdrqQTmfw4fTSU7 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-BCdrqQTmfw4fTSU7 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BCdrqQTmfw4fTSU7 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-BCdrqQTmfw4fTSU7 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-BCdrqQTmfw4fTSU7 .cluster text{fill:#333;}#mermaid-svg-BCdrqQTmfw4fTSU7 .cluster span{color:#333;}#mermaid-svg-BCdrqQTmfw4fTSU7 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-BCdrqQTmfw4fTSU7 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-BCdrqQTmfw4fTSU7 rect.text{fill:none;stroke-width:0;}#mermaid-svg-BCdrqQTmfw4fTSU7 .icon-shape,#mermaid-svg-BCdrqQTmfw4fTSU7 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BCdrqQTmfw4fTSU7 .icon-shape p,#mermaid-svg-BCdrqQTmfw4fTSU7 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-BCdrqQTmfw4fTSU7 .icon-shape .label rect,#mermaid-svg-BCdrqQTmfw4fTSU7 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BCdrqQTmfw4fTSU7 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-BCdrqQTmfw4fTSU7 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-BCdrqQTmfw4fTSU7 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-BCdrqQTmfw4fTSU7 .stage>*{fill:#dbeafe!important;stroke:#2563eb!important;stroke-width:1px!important;color:#1e3a8a!important;}#mermaid-svg-BCdrqQTmfw4fTSU7 .stage span{fill:#dbeafe!important;stroke:#2563eb!important;stroke-width:1px!important;color:#1e3a8a!important;}#mermaid-svg-BCdrqQTmfw4fTSU7 .stage tspan{fill:#1e3a8a!important;} 反向追溯 Backward:每一行代码都对应需求吗?
测试
代码
设计
需求
正向追溯 Forward:每一项需求都实现了吗?
需求
设计
代码
测试
这在安全关键系统中非常重要。当飞机上的某个软件出现故障时,工程师需要能从故障现象一路追溯到原始需求,确认到底是需求错了、设计错了、还是代码错了。
5、V 模型中验证与确认的区别
V 模型中有一个经常被混淆但非常重要的概念区分:
| 概念 | 英文 | 含义 | 对应问题 |
|---|---|---|---|
| 验证 | Verification | 检查产品是否按照规格正确建造 | "我们做对了吗?" |
| 确认 | Validation | 检查建造的产品是否符合用户真实需求 | "我们做了对的东西吗?" |

验证是对系统需求而言的:代码是否实现了设计?设计是否覆盖了需求?
确认是对用户需求而言的:最终产品是否解决了用户的真实问题?
这两者在 V 模型的右臂中处于不同层级------验证工作在底层(单元测试、集成测试),确认工作在顶层(验收测试)。
6、V 模型的优点
6.1、质量内建,而非事后检测
text
瀑布模型:开发完 → "现在来测测看有没有问题"
V 模型: 每个阶段 → "我们已经定义好怎么算合格了,按标准来"
6.2、测试不再是"附属品"
在瀑布模型中,测试经常因为项目延期而被压缩------"前面拖了 3 个月,测试只能压缩到 2 周"。
V 模型将测试提升到了与开发同等的地位,测试计划从项目第一天就开始制定。
6.3、适用于对可靠性要求极高的系统
如果你的代码跑在心脏起搏器、飞机驾驶舱、核电站控制室里,V 模型提供的可追溯性和验证完整性是无价的。
7、V 模型的局限
7.1、本质仍是瀑布
V 模型虽然解决了"测试太晚"的问题,但没有解决瀑布模型更根本的缺陷:需求变化的成本依然极高。
如果用户在 V 模型的右半臂阶段才提出需求变更,整个 V 字从左上角到右下角都要重新来过。
只有完成较多设计后,才能进行对应层级的验证,发现问题可能较晚。
7.2、假设需求可以在早期冻结
和瀑布模型一样,V 模型预设需求在项目初期就能完整、准确地确定。对于探索性、创新型项目,这个假设不成立。
7.3、文档和维护成本高
双向可追溯性不是免费的。
维护完整的需求-设计-代码-测试追溯矩阵需要大量人力和工具支持。
对小团队或快速迭代的项目来说,这个投入产出比可能不划算。
8、V 模型 vs 瀑布模型
#mermaid-svg-W3vuhGcbOaveIEl1{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-W3vuhGcbOaveIEl1 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-W3vuhGcbOaveIEl1 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-W3vuhGcbOaveIEl1 .error-icon{fill:#552222;}#mermaid-svg-W3vuhGcbOaveIEl1 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-W3vuhGcbOaveIEl1 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-W3vuhGcbOaveIEl1 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-W3vuhGcbOaveIEl1 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-W3vuhGcbOaveIEl1 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-W3vuhGcbOaveIEl1 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-W3vuhGcbOaveIEl1 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-W3vuhGcbOaveIEl1 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-W3vuhGcbOaveIEl1 .marker.cross{stroke:#333333;}#mermaid-svg-W3vuhGcbOaveIEl1 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-W3vuhGcbOaveIEl1 p{margin:0;}#mermaid-svg-W3vuhGcbOaveIEl1 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-W3vuhGcbOaveIEl1 .cluster-label text{fill:#333;}#mermaid-svg-W3vuhGcbOaveIEl1 .cluster-label span{color:#333;}#mermaid-svg-W3vuhGcbOaveIEl1 .cluster-label span p{background-color:transparent;}#mermaid-svg-W3vuhGcbOaveIEl1 .label text,#mermaid-svg-W3vuhGcbOaveIEl1 span{fill:#333;color:#333;}#mermaid-svg-W3vuhGcbOaveIEl1 .node rect,#mermaid-svg-W3vuhGcbOaveIEl1 .node circle,#mermaid-svg-W3vuhGcbOaveIEl1 .node ellipse,#mermaid-svg-W3vuhGcbOaveIEl1 .node polygon,#mermaid-svg-W3vuhGcbOaveIEl1 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-W3vuhGcbOaveIEl1 .rough-node .label text,#mermaid-svg-W3vuhGcbOaveIEl1 .node .label text,#mermaid-svg-W3vuhGcbOaveIEl1 .image-shape .label,#mermaid-svg-W3vuhGcbOaveIEl1 .icon-shape .label{text-anchor:middle;}#mermaid-svg-W3vuhGcbOaveIEl1 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-W3vuhGcbOaveIEl1 .rough-node .label,#mermaid-svg-W3vuhGcbOaveIEl1 .node .label,#mermaid-svg-W3vuhGcbOaveIEl1 .image-shape .label,#mermaid-svg-W3vuhGcbOaveIEl1 .icon-shape .label{text-align:center;}#mermaid-svg-W3vuhGcbOaveIEl1 .node.clickable{cursor:pointer;}#mermaid-svg-W3vuhGcbOaveIEl1 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-W3vuhGcbOaveIEl1 .arrowheadPath{fill:#333333;}#mermaid-svg-W3vuhGcbOaveIEl1 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-W3vuhGcbOaveIEl1 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-W3vuhGcbOaveIEl1 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-W3vuhGcbOaveIEl1 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-W3vuhGcbOaveIEl1 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-W3vuhGcbOaveIEl1 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-W3vuhGcbOaveIEl1 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-W3vuhGcbOaveIEl1 .cluster text{fill:#333;}#mermaid-svg-W3vuhGcbOaveIEl1 .cluster span{color:#333;}#mermaid-svg-W3vuhGcbOaveIEl1 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-W3vuhGcbOaveIEl1 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-W3vuhGcbOaveIEl1 rect.text{fill:none;stroke-width:0;}#mermaid-svg-W3vuhGcbOaveIEl1 .icon-shape,#mermaid-svg-W3vuhGcbOaveIEl1 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-W3vuhGcbOaveIEl1 .icon-shape p,#mermaid-svg-W3vuhGcbOaveIEl1 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-W3vuhGcbOaveIEl1 .icon-shape .label rect,#mermaid-svg-W3vuhGcbOaveIEl1 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-W3vuhGcbOaveIEl1 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-W3vuhGcbOaveIEl1 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-W3vuhGcbOaveIEl1 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-W3vuhGcbOaveIEl1 .stage>*{fill:#dbeafe!important;stroke:#2563eb!important;stroke-width:1px!important;color:#1e3a8a!important;}#mermaid-svg-W3vuhGcbOaveIEl1 .stage span{fill:#dbeafe!important;stroke:#2563eb!important;stroke-width:1px!important;color:#1e3a8a!important;}#mermaid-svg-W3vuhGcbOaveIEl1 .stage tspan{fill:#1e3a8a!important;}#mermaid-svg-W3vuhGcbOaveIEl1 .test>*{fill:#dcfce7!important;stroke:#16a34a!important;stroke-width:1px!important;color:#14532b!important;}#mermaid-svg-W3vuhGcbOaveIEl1 .test span{fill:#dcfce7!important;stroke:#16a34a!important;stroke-width:1px!important;color:#14532b!important;}#mermaid-svg-W3vuhGcbOaveIEl1 .test tspan{fill:#14532b!important;} V 模型:测试是开发的并行活动
对应
对应
对应
对应
需求
设计
详细设计
编码
验收测试
系统测试
集成测试
单元测试
瀑布模型:测试是开发的后续步骤
需求
设计
编码
测试
上线
9、AI 时代的思考
V 模型的可追溯性思想在 AI 辅助开发中意外地很有启发。当 AI 生成了 500 行代码之后,一个很好的习惯是追问:
text
"这段代码对应的是哪条需求?"
"有没有生成需求之外的功能(过度工程)?"
"每个函数是否可以对应到某个测试用例?"
这本质上就是在实践 V 模型的双向追溯------只不过不是用文档矩阵,而是用 Code Review 中的追问来实现。在 AI 输出量爆炸的时代,保持"每一行代码都有出处"的追溯意识,反而比以前更重要了。
每一个 Workflow 都要有回路(借鉴 Validation),不要只验证"代码是否能运行",还要验证:
- 是否真正解决了用户问题?
- 是否满足业务目标?
- 是否符合性能、成本和安全要求?
也就是说,不仅验证实现正确(Verification),还要验证目标正确(Validation)。
10、本篇要点速记
text
V 模型 = 瀑布模型 + 测试前置 + 双向可追溯
诞生于 1980 年代,源自德国联邦政府 IT 系统开发标准。
核心思想:每一个开发阶段都对应一个测试阶段。
关键区分:Verification(做对了)vs Validation(做了对的)
优点 → 质量内建、测试与开发对等、可追溯性强
局限 → 本质仍是瀑布、需求变更成本高、文档负担重
一句话:V 模型教会我们"验证标准要在动手之前想好"。
设计思想(最本质):每个设计产物都必须有对应的验证手段(Every Design Has a Verification)。
工程能力(最重要):建立需求→设计→实现→测试的双向可追溯性(Traceability)。
最终目标(最高层):保证系统能够被证明是正确的(Evidence-based Quality),即不仅"相信它是对的",而且能拿出完整证据链证明它为什么是对的。
附录:从"测试"到"证据链"------对 V 模型更深一层的理解
把 V 模型右臂的"验证"按层级展开:代码(第一层)→ 模块(第二层)→ 架构(第三层)→ 需求(第四层)。越往上,验证就越不像"跑测试",越像"拿证据"。
第三层:架构验证(很多人开始模糊)
举个器人的例子。架构是:
#mermaid-svg-039Tu8vXZjVcTppE{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-039Tu8vXZjVcTppE .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-039Tu8vXZjVcTppE .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-039Tu8vXZjVcTppE .error-icon{fill:#552222;}#mermaid-svg-039Tu8vXZjVcTppE .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-039Tu8vXZjVcTppE .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-039Tu8vXZjVcTppE .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-039Tu8vXZjVcTppE .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-039Tu8vXZjVcTppE .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-039Tu8vXZjVcTppE .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-039Tu8vXZjVcTppE .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-039Tu8vXZjVcTppE .marker{fill:#333333;stroke:#333333;}#mermaid-svg-039Tu8vXZjVcTppE .marker.cross{stroke:#333333;}#mermaid-svg-039Tu8vXZjVcTppE svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-039Tu8vXZjVcTppE p{margin:0;}#mermaid-svg-039Tu8vXZjVcTppE .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-039Tu8vXZjVcTppE .cluster-label text{fill:#333;}#mermaid-svg-039Tu8vXZjVcTppE .cluster-label span{color:#333;}#mermaid-svg-039Tu8vXZjVcTppE .cluster-label span p{background-color:transparent;}#mermaid-svg-039Tu8vXZjVcTppE .label text,#mermaid-svg-039Tu8vXZjVcTppE span{fill:#333;color:#333;}#mermaid-svg-039Tu8vXZjVcTppE .node rect,#mermaid-svg-039Tu8vXZjVcTppE .node circle,#mermaid-svg-039Tu8vXZjVcTppE .node ellipse,#mermaid-svg-039Tu8vXZjVcTppE .node polygon,#mermaid-svg-039Tu8vXZjVcTppE .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-039Tu8vXZjVcTppE .rough-node .label text,#mermaid-svg-039Tu8vXZjVcTppE .node .label text,#mermaid-svg-039Tu8vXZjVcTppE .image-shape .label,#mermaid-svg-039Tu8vXZjVcTppE .icon-shape .label{text-anchor:middle;}#mermaid-svg-039Tu8vXZjVcTppE .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-039Tu8vXZjVcTppE .rough-node .label,#mermaid-svg-039Tu8vXZjVcTppE .node .label,#mermaid-svg-039Tu8vXZjVcTppE .image-shape .label,#mermaid-svg-039Tu8vXZjVcTppE .icon-shape .label{text-align:center;}#mermaid-svg-039Tu8vXZjVcTppE .node.clickable{cursor:pointer;}#mermaid-svg-039Tu8vXZjVcTppE .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-039Tu8vXZjVcTppE .arrowheadPath{fill:#333333;}#mermaid-svg-039Tu8vXZjVcTppE .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-039Tu8vXZjVcTppE .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-039Tu8vXZjVcTppE .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-039Tu8vXZjVcTppE .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-039Tu8vXZjVcTppE .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-039Tu8vXZjVcTppE .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-039Tu8vXZjVcTppE .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-039Tu8vXZjVcTppE .cluster text{fill:#333;}#mermaid-svg-039Tu8vXZjVcTppE .cluster span{color:#333;}#mermaid-svg-039Tu8vXZjVcTppE div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-039Tu8vXZjVcTppE .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-039Tu8vXZjVcTppE rect.text{fill:none;stroke-width:0;}#mermaid-svg-039Tu8vXZjVcTppE .icon-shape,#mermaid-svg-039Tu8vXZjVcTppE .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-039Tu8vXZjVcTppE .icon-shape p,#mermaid-svg-039Tu8vXZjVcTppE .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-039Tu8vXZjVcTppE .icon-shape .label rect,#mermaid-svg-039Tu8vXZjVcTppE .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-039Tu8vXZjVcTppE .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-039Tu8vXZjVcTppE .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-039Tu8vXZjVcTppE :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-039Tu8vXZjVcTppE .stage>*{fill:#dbeafe!important;stroke:#2563eb!important;stroke-width:1px!important;color:#1e3a8a!important;}#mermaid-svg-039Tu8vXZjVcTppE .stage span{fill:#dbeafe!important;stroke:#2563eb!important;stroke-width:1px!important;color:#1e3a8a!important;}#mermaid-svg-039Tu8vXZjVcTppE .stage tspan{fill:#1e3a8a!important;} Camera
Stereo
Detection
Planner
Motor
老板问"为什么这样设计?",如果你只能回答"不知道"------那说明架构没有被验证。
真正的架构验证是什么?比如你的目标是 30 FPS,于是架构设计成:
#mermaid-svg-QIxxLSVu6lN6gWXc{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-QIxxLSVu6lN6gWXc .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-QIxxLSVu6lN6gWXc .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-QIxxLSVu6lN6gWXc .error-icon{fill:#552222;}#mermaid-svg-QIxxLSVu6lN6gWXc .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-QIxxLSVu6lN6gWXc .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-QIxxLSVu6lN6gWXc .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-QIxxLSVu6lN6gWXc .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-QIxxLSVu6lN6gWXc .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-QIxxLSVu6lN6gWXc .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-QIxxLSVu6lN6gWXc .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-QIxxLSVu6lN6gWXc .marker{fill:#333333;stroke:#333333;}#mermaid-svg-QIxxLSVu6lN6gWXc .marker.cross{stroke:#333333;}#mermaid-svg-QIxxLSVu6lN6gWXc svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-QIxxLSVu6lN6gWXc p{margin:0;}#mermaid-svg-QIxxLSVu6lN6gWXc .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-QIxxLSVu6lN6gWXc .cluster-label text{fill:#333;}#mermaid-svg-QIxxLSVu6lN6gWXc .cluster-label span{color:#333;}#mermaid-svg-QIxxLSVu6lN6gWXc .cluster-label span p{background-color:transparent;}#mermaid-svg-QIxxLSVu6lN6gWXc .label text,#mermaid-svg-QIxxLSVu6lN6gWXc span{fill:#333;color:#333;}#mermaid-svg-QIxxLSVu6lN6gWXc .node rect,#mermaid-svg-QIxxLSVu6lN6gWXc .node circle,#mermaid-svg-QIxxLSVu6lN6gWXc .node ellipse,#mermaid-svg-QIxxLSVu6lN6gWXc .node polygon,#mermaid-svg-QIxxLSVu6lN6gWXc .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-QIxxLSVu6lN6gWXc .rough-node .label text,#mermaid-svg-QIxxLSVu6lN6gWXc .node .label text,#mermaid-svg-QIxxLSVu6lN6gWXc .image-shape .label,#mermaid-svg-QIxxLSVu6lN6gWXc .icon-shape .label{text-anchor:middle;}#mermaid-svg-QIxxLSVu6lN6gWXc .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-QIxxLSVu6lN6gWXc .rough-node .label,#mermaid-svg-QIxxLSVu6lN6gWXc .node .label,#mermaid-svg-QIxxLSVu6lN6gWXc .image-shape .label,#mermaid-svg-QIxxLSVu6lN6gWXc .icon-shape .label{text-align:center;}#mermaid-svg-QIxxLSVu6lN6gWXc .node.clickable{cursor:pointer;}#mermaid-svg-QIxxLSVu6lN6gWXc .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-QIxxLSVu6lN6gWXc .arrowheadPath{fill:#333333;}#mermaid-svg-QIxxLSVu6lN6gWXc .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-QIxxLSVu6lN6gWXc .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-QIxxLSVu6lN6gWXc .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-QIxxLSVu6lN6gWXc .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-QIxxLSVu6lN6gWXc .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-QIxxLSVu6lN6gWXc .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-QIxxLSVu6lN6gWXc .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-QIxxLSVu6lN6gWXc .cluster text{fill:#333;}#mermaid-svg-QIxxLSVu6lN6gWXc .cluster span{color:#333;}#mermaid-svg-QIxxLSVu6lN6gWXc div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-QIxxLSVu6lN6gWXc .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-QIxxLSVu6lN6gWXc rect.text{fill:none;stroke-width:0;}#mermaid-svg-QIxxLSVu6lN6gWXc .icon-shape,#mermaid-svg-QIxxLSVu6lN6gWXc .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-QIxxLSVu6lN6gWXc .icon-shape p,#mermaid-svg-QIxxLSVu6lN6gWXc .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-QIxxLSVu6lN6gWXc .icon-shape .label rect,#mermaid-svg-QIxxLSVu6lN6gWXc .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-QIxxLSVu6lN6gWXc .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-QIxxLSVu6lN6gWXc .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-QIxxLSVu6lN6gWXc :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-QIxxLSVu6lN6gWXc .stage>*{fill:#dbeafe!important;stroke:#2563eb!important;stroke-width:1px!important;color:#1e3a8a!important;}#mermaid-svg-QIxxLSVu6lN6gWXc .stage span{fill:#dbeafe!important;stroke:#2563eb!important;stroke-width:1px!important;color:#1e3a8a!important;}#mermaid-svg-QIxxLSVu6lN6gWXc .stage tspan{fill:#1e3a8a!important;} GPU
Stereo
CPU
Planner
为什么这么设计?因为经过 Benchmark 实测 FPS = 32。也就是说:
#mermaid-svg-CEmfbiZUoMe9sUW4{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-CEmfbiZUoMe9sUW4 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-CEmfbiZUoMe9sUW4 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-CEmfbiZUoMe9sUW4 .error-icon{fill:#552222;}#mermaid-svg-CEmfbiZUoMe9sUW4 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-CEmfbiZUoMe9sUW4 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-CEmfbiZUoMe9sUW4 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-CEmfbiZUoMe9sUW4 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-CEmfbiZUoMe9sUW4 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-CEmfbiZUoMe9sUW4 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-CEmfbiZUoMe9sUW4 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-CEmfbiZUoMe9sUW4 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-CEmfbiZUoMe9sUW4 .marker.cross{stroke:#333333;}#mermaid-svg-CEmfbiZUoMe9sUW4 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-CEmfbiZUoMe9sUW4 p{margin:0;}#mermaid-svg-CEmfbiZUoMe9sUW4 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-CEmfbiZUoMe9sUW4 .cluster-label text{fill:#333;}#mermaid-svg-CEmfbiZUoMe9sUW4 .cluster-label span{color:#333;}#mermaid-svg-CEmfbiZUoMe9sUW4 .cluster-label span p{background-color:transparent;}#mermaid-svg-CEmfbiZUoMe9sUW4 .label text,#mermaid-svg-CEmfbiZUoMe9sUW4 span{fill:#333;color:#333;}#mermaid-svg-CEmfbiZUoMe9sUW4 .node rect,#mermaid-svg-CEmfbiZUoMe9sUW4 .node circle,#mermaid-svg-CEmfbiZUoMe9sUW4 .node ellipse,#mermaid-svg-CEmfbiZUoMe9sUW4 .node polygon,#mermaid-svg-CEmfbiZUoMe9sUW4 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-CEmfbiZUoMe9sUW4 .rough-node .label text,#mermaid-svg-CEmfbiZUoMe9sUW4 .node .label text,#mermaid-svg-CEmfbiZUoMe9sUW4 .image-shape .label,#mermaid-svg-CEmfbiZUoMe9sUW4 .icon-shape .label{text-anchor:middle;}#mermaid-svg-CEmfbiZUoMe9sUW4 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-CEmfbiZUoMe9sUW4 .rough-node .label,#mermaid-svg-CEmfbiZUoMe9sUW4 .node .label,#mermaid-svg-CEmfbiZUoMe9sUW4 .image-shape .label,#mermaid-svg-CEmfbiZUoMe9sUW4 .icon-shape .label{text-align:center;}#mermaid-svg-CEmfbiZUoMe9sUW4 .node.clickable{cursor:pointer;}#mermaid-svg-CEmfbiZUoMe9sUW4 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-CEmfbiZUoMe9sUW4 .arrowheadPath{fill:#333333;}#mermaid-svg-CEmfbiZUoMe9sUW4 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-CEmfbiZUoMe9sUW4 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-CEmfbiZUoMe9sUW4 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CEmfbiZUoMe9sUW4 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-CEmfbiZUoMe9sUW4 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CEmfbiZUoMe9sUW4 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-CEmfbiZUoMe9sUW4 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-CEmfbiZUoMe9sUW4 .cluster text{fill:#333;}#mermaid-svg-CEmfbiZUoMe9sUW4 .cluster span{color:#333;}#mermaid-svg-CEmfbiZUoMe9sUW4 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-CEmfbiZUoMe9sUW4 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-CEmfbiZUoMe9sUW4 rect.text{fill:none;stroke-width:0;}#mermaid-svg-CEmfbiZUoMe9sUW4 .icon-shape,#mermaid-svg-CEmfbiZUoMe9sUW4 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CEmfbiZUoMe9sUW4 .icon-shape p,#mermaid-svg-CEmfbiZUoMe9sUW4 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-CEmfbiZUoMe9sUW4 .icon-shape .label rect,#mermaid-svg-CEmfbiZUoMe9sUW4 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CEmfbiZUoMe9sUW4 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-CEmfbiZUoMe9sUW4 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-CEmfbiZUoMe9sUW4 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-CEmfbiZUoMe9sUW4 .stage>*{fill:#dbeafe!important;stroke:#2563eb!important;stroke-width:1px!important;color:#1e3a8a!important;}#mermaid-svg-CEmfbiZUoMe9sUW4 .stage span{fill:#dbeafe!important;stroke:#2563eb!important;stroke-width:1px!important;color:#1e3a8a!important;}#mermaid-svg-CEmfbiZUoMe9sUW4 .stage tspan{fill:#1e3a8a!important;} Architecture
Evidence
Benchmark
所以架构验证不是"代码能跑",而是架构目标有没有达到------性能 ✓、稳定 ✓、扩展 ✓、容错 ✓、成本 ✓,这些都是 Architecture Validation。
再比如老板问"为什么不用 Monolithic 而用 Microservice?",你的证据是 1000 TPS、CPU、Latency、Deployment 等指标------这些就是 Architecture Evidence,而不是 Unit Test。
第四层:需求验证(最容易误解)
需求是"用户需要扫码登录",开发完成后怎么验证?很多人说"跑测试"------不是。真正的验证应该问:
用户真的喜欢扫码登录吗?
比如上线一周后,95% 的用户都在扫码,说明需求成立;或者做 A/B Test(短信登录 VS 扫码登录),结果扫码留存率 +18%。那么:
#mermaid-svg-JO4FDS9AzU5CfI2f{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-JO4FDS9AzU5CfI2f .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-JO4FDS9AzU5CfI2f .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-JO4FDS9AzU5CfI2f .error-icon{fill:#552222;}#mermaid-svg-JO4FDS9AzU5CfI2f .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-JO4FDS9AzU5CfI2f .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-JO4FDS9AzU5CfI2f .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-JO4FDS9AzU5CfI2f .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-JO4FDS9AzU5CfI2f .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-JO4FDS9AzU5CfI2f .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-JO4FDS9AzU5CfI2f .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-JO4FDS9AzU5CfI2f .marker{fill:#333333;stroke:#333333;}#mermaid-svg-JO4FDS9AzU5CfI2f .marker.cross{stroke:#333333;}#mermaid-svg-JO4FDS9AzU5CfI2f svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-JO4FDS9AzU5CfI2f p{margin:0;}#mermaid-svg-JO4FDS9AzU5CfI2f .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-JO4FDS9AzU5CfI2f .cluster-label text{fill:#333;}#mermaid-svg-JO4FDS9AzU5CfI2f .cluster-label span{color:#333;}#mermaid-svg-JO4FDS9AzU5CfI2f .cluster-label span p{background-color:transparent;}#mermaid-svg-JO4FDS9AzU5CfI2f .label text,#mermaid-svg-JO4FDS9AzU5CfI2f span{fill:#333;color:#333;}#mermaid-svg-JO4FDS9AzU5CfI2f .node rect,#mermaid-svg-JO4FDS9AzU5CfI2f .node circle,#mermaid-svg-JO4FDS9AzU5CfI2f .node ellipse,#mermaid-svg-JO4FDS9AzU5CfI2f .node polygon,#mermaid-svg-JO4FDS9AzU5CfI2f .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-JO4FDS9AzU5CfI2f .rough-node .label text,#mermaid-svg-JO4FDS9AzU5CfI2f .node .label text,#mermaid-svg-JO4FDS9AzU5CfI2f .image-shape .label,#mermaid-svg-JO4FDS9AzU5CfI2f .icon-shape .label{text-anchor:middle;}#mermaid-svg-JO4FDS9AzU5CfI2f .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-JO4FDS9AzU5CfI2f .rough-node .label,#mermaid-svg-JO4FDS9AzU5CfI2f .node .label,#mermaid-svg-JO4FDS9AzU5CfI2f .image-shape .label,#mermaid-svg-JO4FDS9AzU5CfI2f .icon-shape .label{text-align:center;}#mermaid-svg-JO4FDS9AzU5CfI2f .node.clickable{cursor:pointer;}#mermaid-svg-JO4FDS9AzU5CfI2f .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-JO4FDS9AzU5CfI2f .arrowheadPath{fill:#333333;}#mermaid-svg-JO4FDS9AzU5CfI2f .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-JO4FDS9AzU5CfI2f .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-JO4FDS9AzU5CfI2f .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-JO4FDS9AzU5CfI2f .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-JO4FDS9AzU5CfI2f .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-JO4FDS9AzU5CfI2f .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-JO4FDS9AzU5CfI2f .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-JO4FDS9AzU5CfI2f .cluster text{fill:#333;}#mermaid-svg-JO4FDS9AzU5CfI2f .cluster span{color:#333;}#mermaid-svg-JO4FDS9AzU5CfI2f div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-JO4FDS9AzU5CfI2f .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-JO4FDS9AzU5CfI2f rect.text{fill:none;stroke-width:0;}#mermaid-svg-JO4FDS9AzU5CfI2f .icon-shape,#mermaid-svg-JO4FDS9AzU5CfI2f .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-JO4FDS9AzU5CfI2f .icon-shape p,#mermaid-svg-JO4FDS9AzU5CfI2f .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-JO4FDS9AzU5CfI2f .icon-shape .label rect,#mermaid-svg-JO4FDS9AzU5CfI2f .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-JO4FDS9AzU5CfI2f .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-JO4FDS9AzU5CfI2f .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-JO4FDS9AzU5CfI2f :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-JO4FDS9AzU5CfI2f .stage>*{fill:#dbeafe!important;stroke:#2563eb!important;stroke-width:1px!important;color:#1e3a8a!important;}#mermaid-svg-JO4FDS9AzU5CfI2f .stage span{fill:#dbeafe!important;stroke:#2563eb!important;stroke-width:1px!important;color:#1e3a8a!important;}#mermaid-svg-JO4FDS9AzU5CfI2f .stage tspan{fill:#1e3a8a!important;} Requirement
Evidence
Business Metrics
所以需求验证很多时候不是 QA(Quality Assurance) 做,而是产品经理、运营、甚至市场来做------因为需求正确与否,最后要靠业务数据,不是测试用例。
高级别 Validation 长什么样?
它越来越不像 Test Case,越来越像 Evidence:
| Artifact | Verification Evidence |
|---|---|
| Requirement | 用户访谈、A/B Test、业务指标、客户验收 |
| Architecture | Benchmark、压测、容量评估、故障演练 |
| Detailed Design | Design Review、Simulation、Prototype |
| Module | Integration Test |
| Code | Unit Test |
越往上,越不像 JUnit,越像 Review、Experiment、Benchmark、Pilot、Simulation。
Artifact(制品/工件) 指的是在开发过程中产生的、具有特定价值的文档、代码、数据或成果物。
V-Model 右边,其实不是 Test
这是我后来理解最深的一点。教材写的是 Requirement → Acceptance Test,其实更准确应该写成 Requirement → Evidence:
#mermaid-svg-lSLAEgqLJDX849ac{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-lSLAEgqLJDX849ac .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-lSLAEgqLJDX849ac .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-lSLAEgqLJDX849ac .error-icon{fill:#552222;}#mermaid-svg-lSLAEgqLJDX849ac .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-lSLAEgqLJDX849ac .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-lSLAEgqLJDX849ac .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-lSLAEgqLJDX849ac .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-lSLAEgqLJDX849ac .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-lSLAEgqLJDX849ac .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-lSLAEgqLJDX849ac .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-lSLAEgqLJDX849ac .marker{fill:#333333;stroke:#333333;}#mermaid-svg-lSLAEgqLJDX849ac .marker.cross{stroke:#333333;}#mermaid-svg-lSLAEgqLJDX849ac svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-lSLAEgqLJDX849ac p{margin:0;}#mermaid-svg-lSLAEgqLJDX849ac .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-lSLAEgqLJDX849ac .cluster-label text{fill:#333;}#mermaid-svg-lSLAEgqLJDX849ac .cluster-label span{color:#333;}#mermaid-svg-lSLAEgqLJDX849ac .cluster-label span p{background-color:transparent;}#mermaid-svg-lSLAEgqLJDX849ac .label text,#mermaid-svg-lSLAEgqLJDX849ac span{fill:#333;color:#333;}#mermaid-svg-lSLAEgqLJDX849ac .node rect,#mermaid-svg-lSLAEgqLJDX849ac .node circle,#mermaid-svg-lSLAEgqLJDX849ac .node ellipse,#mermaid-svg-lSLAEgqLJDX849ac .node polygon,#mermaid-svg-lSLAEgqLJDX849ac .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-lSLAEgqLJDX849ac .rough-node .label text,#mermaid-svg-lSLAEgqLJDX849ac .node .label text,#mermaid-svg-lSLAEgqLJDX849ac .image-shape .label,#mermaid-svg-lSLAEgqLJDX849ac .icon-shape .label{text-anchor:middle;}#mermaid-svg-lSLAEgqLJDX849ac .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-lSLAEgqLJDX849ac .rough-node .label,#mermaid-svg-lSLAEgqLJDX849ac .node .label,#mermaid-svg-lSLAEgqLJDX849ac .image-shape .label,#mermaid-svg-lSLAEgqLJDX849ac .icon-shape .label{text-align:center;}#mermaid-svg-lSLAEgqLJDX849ac .node.clickable{cursor:pointer;}#mermaid-svg-lSLAEgqLJDX849ac .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-lSLAEgqLJDX849ac .arrowheadPath{fill:#333333;}#mermaid-svg-lSLAEgqLJDX849ac .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-lSLAEgqLJDX849ac .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-lSLAEgqLJDX849ac .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-lSLAEgqLJDX849ac .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-lSLAEgqLJDX849ac .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-lSLAEgqLJDX849ac .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-lSLAEgqLJDX849ac .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-lSLAEgqLJDX849ac .cluster text{fill:#333;}#mermaid-svg-lSLAEgqLJDX849ac .cluster span{color:#333;}#mermaid-svg-lSLAEgqLJDX849ac div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-lSLAEgqLJDX849ac .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-lSLAEgqLJDX849ac rect.text{fill:none;stroke-width:0;}#mermaid-svg-lSLAEgqLJDX849ac .icon-shape,#mermaid-svg-lSLAEgqLJDX849ac .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-lSLAEgqLJDX849ac .icon-shape p,#mermaid-svg-lSLAEgqLJDX849ac .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-lSLAEgqLJDX849ac .icon-shape .label rect,#mermaid-svg-lSLAEgqLJDX849ac .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-lSLAEgqLJDX849ac .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-lSLAEgqLJDX849ac .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-lSLAEgqLJDX849ac :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-lSLAEgqLJDX849ac .stage>*{fill:#dbeafe!important;stroke:#2563eb!important;stroke-width:1px!important;color:#1e3a8a!important;}#mermaid-svg-lSLAEgqLJDX849ac .stage span{fill:#dbeafe!important;stroke:#2563eb!important;stroke-width:1px!important;color:#1e3a8a!important;}#mermaid-svg-lSLAEgqLJDX849ac .stage tspan{fill:#1e3a8a!important;}#mermaid-svg-lSLAEgqLJDX849ac .test>*{fill:#dcfce7!important;stroke:#16a34a!important;stroke-width:1px!important;color:#14532b!important;}#mermaid-svg-lSLAEgqLJDX849ac .test span{fill:#dcfce7!important;stroke:#16a34a!important;stroke-width:1px!important;color:#14532b!important;}#mermaid-svg-lSLAEgqLJDX849ac .test tspan{fill:#14532b!important;} Requirement
Acceptance Test
(教材写法)
Requirement
Evidence
(更准确)
比如需求是"机器人避障成功率 99%",Evidence 是"1000 次家庭测试,998 次成功"------不是 Test Case,而是 Evidence。
AI Agent 时代,这个思想反而越来越重要
- Agent 生成了一份架构,怎么验证?不是
pytest,而是压力测试看 Latency 是否满足(PASS)。 - Agent 生成了 Prompt,怎么验证?不是 Compile,而是用 1000 个样本看 Accuracy = 96%。
- Agent 写了 Workflow,怎么验证?不是看代码,而是看任务成功率 ≥ 95%。
所以 AI 时代,Verification 越来越不像 Test,越来越像 Evaluation------这也是为什么 LLM 社区用的词是 Evaluation 而不是 Testing。
最本质的一句话
我已经不再把 V-Model 理解成"开发对应测试",而是:
开发过程中的每一个决策(Decision),都必须留下能够证明它正确的证据(Evidence)。
代码的证据是 Unit Test;模块的证据是 Integration Test;架构的证据是 Benchmark、性能测试、故障演练和架构评审;需求的证据则是用户验收、A/B Test、业务指标、用户反馈。
所以,V 模型真正管理的不是测试,而是证据链(Chain of Evidence)。这也是为什么航空航天、医疗器械、自动驾驶等安全关键行业至今仍大量采用 V-Model:当有人问"为什么你确信这个系统是正确的?"时,它能拿出从需求到设计、从设计到实现、从实现到验证的完整证据链,而不仅仅是一堆测试报告。

上一篇:瀑布模型
下一篇:螺旋模型