当前位置:首页  >  IT问答库  >  软件测试基础知识

软件测试中的验证与确认有什么区别_千锋教育

发布:cli 2026-05-29 06:11

推荐答案

01 验证与确认:一字之差,生死之别

2018年,某电商平台在双11前夕上线新功能。测试团队用3天完成了全部“验证”:功能正常、页面兼容、性能达标。上线后,用户点击“立即购买”却跳转到404页面。原因?产品经理的PRD写的是“点击跳转支付页”,开发理解成了“点击跳转商品详情页”,测试验证的是“跳转逻辑是否正确”。

结果: 1小时损失2000万GMV。

问题出在哪?测试团队只做了“验证”(Verification),没做“确认”(Validation)。验证检查的是“产品是否按规格实现”,确认检查的是“产品是否满足用户真实需求”。

数据说话:

  • ►仅做验证的项目,上线后用户投诉率高达34%
  • ►验证+确认的项目,用户满意度提升82%
  • ►确认环节缺失导致的需求偏差,占软件缺陷的56%

核心区别表:

维度验证确认
问句我们做对了吗?我们做了对的吗?
对象需求文档、设计稿用户真实场景、业务目标
时机开发过程中开发前后
标准文档/规范用户满意度
方法代码审查、单元测试用户验收测试、A/B测试

验证是照镜子,确认是看路标。

---

02 验证的7种武器:检查代码是否“照镜子”

验证是测试的基础功。它回答“系统是否按设计实现”这个技术问题。以下是7种实战验证方法:

1. 代码审查

  • ►操作: 开发完成后,另一个开发逐行检查代码
  • ►效率: 能发现60%以上的逻辑错误
  • ►代码示例:

错误代码(验证失败)

def calculate_discount(price):

return price * 0.9 # 写死折扣为9折

正确代码(验证通过)

def calculate_discount(price, discount_rate=0.1):

return price * (1 - discount_rate)

text

<div style="margin:24px 0;border:1px solid #E3F2FD;border-radius:8px;background:#FAFAFA;overflow:hidden;"><div style="display:flex;align-items:center;gap:12px;padding:12px 20px;background:linear-gradient(135deg,#E3F2FD,#BBDEFB);"><span style="width:36px;height:36px;background:#2196F3;color:#fff;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-weight:bold;font-size:16px;flex-shrink:0;">2. </span><span style="font-size:17px;font-weight:700;color:#1565C0;">单元测试</span></div><div style="padding:16px 20px;"><ul style="list-style:none;padding-left:0;margin:12px 0;">
<li style="position:relative;padding:4px 0 4px 24px;line-height:1.8;"><span style="color:#2196F3;font-weight:bold;position:absolute;left:4px;">&#9658;</span><strong>覆盖率要求:</strong> 语句覆盖≥90%,分支覆盖≥80%</li>
<li style="position:relative;padding:4px 0 4px 24px;line-height:1.8;"><span style="color:#2196F3;font-weight:bold;position:absolute;left:4px;">&#9658;</span><strong>工具:</strong> JUnit(Java)、pytest(Python)</li>
<li style="position:relative;padding:4px 0 4px 24px;line-height:1.8;"><span style="color:#2196F3;font-weight:bold;position:absolute;left:4px;">&#9658;</span><strong>示例:</strong></li>
</ul>
<div style="margin:16px 0;border-radius:8px;overflow:hidden;border:1px solid #E0E0E0;"><div style="background:#263238;color:#B0BEC5;padding:6px 16px;font-size:12px;font-family:Consolas,monospace;"><span style="text-transform:uppercase;letter-spacing:1px;">python</span></div><pre style="background:#1E272E;color:#E0E0E0;padding:16px 20px;margin:0;overflow-x:auto;font-size:14px;line-height:1.7;font-family:Consolas,"Courier New",monospace;"><code>def test_calculate_discount():
    assert calculate_discount(100, 0.1) == 90
    assert calculate_discount(200, 0.2) == 160</code></pre></div></div></div>
<div style="margin:24px 0;border:1px solid #E3F2FD;border-radius:8px;background:#FAFAFA;overflow:hidden;"><div style="display:flex;align-items:center;gap:12px;padding:12px 20px;background:linear-gradient(135deg,#E3F2FD,#BBDEFB);"><span style="width:36px;height:36px;background:#2196F3;color:#fff;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-weight:bold;font-size:16px;flex-shrink:0;">3. </span><span style="font-size:17px;font-weight:700;color:#1565C0;">接口测试</span></div><div style="padding:16px 20px;"><ul style="list-style:none;padding-left:0;margin:12px 0;">
<li style="position:relative;padding:4px 0 4px 24px;line-height:1.8;"><span style="color:#2196F3;font-weight:bold;position:absolute;left:4px;">&#9658;</span><strong>检查点:</strong> 请求格式、响应状态码、数据字段完整性</li>
<li style="position:relative;padding:4px 0 4px 24px;line-height:1.8;"><span style="color:#2196F3;font-weight:bold;position:absolute;left:4px;">&#9658;</span><strong>工具:</strong> Postman、JMeter</li>
<li style="position:relative;padding:4px 0 4px 24px;line-height:1.8;"><span style="color:#2196F3;font-weight:bold;position:absolute;left:4px;">&#9658;</span><strong>断言示例:</strong></li>
</ul>
<div style="margin:16px 0;border-radius:8px;overflow:hidden;border:1px solid #E0E0E0;"><div style="background:#263238;color:#B0BEC5;padding:6px 16px;font-size:12px;font-family:Consolas,monospace;"><span style="text-transform:uppercase;letter-spacing:1px;">javascript</span></div><pre style="background:#1E272E;color:#E0E0E0;padding:16px 20px;margin:0;overflow-x:auto;font-size:14px;line-height:1.7;font-family:Consolas,"Courier New",monospace;"><code>pm.test("Status code is 200", function () {
    pm.response.to.have.status(200);
});
pm.test("Response has user_id field", function () {
    var jsonData = pm.response.json();
    pm.expect(jsonData).to.have.property('user_id');
});</code></pre></div></div></div>
<div style="margin:24px 0;border:1px solid #E3F2FD;border-radius:8px;background:#FAFAFA;overflow:hidden;"><div style="display:flex;align-items:center;gap:12px;padding:12px 20px;background:linear-gradient(135deg,#E3F2FD,#BBDEFB);"><span style="width:36px;height:36px;background:#2196F3;color:#fff;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-weight:bold;font-size:16px;flex-shrink:0;">4. </span><span style="font-size:17px;font-weight:700;color:#1565C0;">集成测试</span></div><div style="padding:16px 20px;"><ul style="list-style:none;padding-left:0;margin:12px 0;">
<li style="position:relative;padding:4px 0 4px 24px;line-height:1.8;"><span style="color:#2196F3;font-weight:bold;position:absolute;left:4px;">&#9658;</span><strong>范围:</strong> 模块间的数据流转、服务调用链</li>
<li style="position:relative;padding:4px 0 4px 24px;line-height:1.8;"><span style="color:#2196F3;font-weight:bold;position:absolute;left:4px;">&#9658;</span><strong>重点:</strong> 数据库连接、消息队列、第三方API</li>
</ul></div></div>
<div style="margin:24px 0;border:1px solid #E3F2FD;border-radius:8px;background:#FAFAFA;overflow:hidden;"><div style="display:flex;align-items:center;gap:12px;padding:12px 20px;background:linear-gradient(135deg,#E3F2FD,#BBDEFB);"><span style="width:36px;height:36px;background:#2196F3;color:#fff;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-weight:bold;font-size:16px;flex-shrink:0;">5. </span><span style="font-size:17px;font-weight:700;color:#1565C0;">系统测试</span></div><div style="padding:16px 20px;"><ul style="list-style:none;padding-left:0;margin:12px 0;">
<li style="position:relative;padding:4px 0 4px 24px;line-height:1.8;"><span style="color:#2196F3;font-weight:bold;position:absolute;left:4px;">&#9658;</span><strong>维度:</strong> 功能、性能、安全、兼容性</li>
<li style="position:relative;padding:4px 0 4px 24px;line-height:1.8;"><span style="color:#2196F3;font-weight:bold;position:absolute;left:4px;">&#9658;</span><strong>指标:</strong> 响应时间<2秒,并发用户>1000,零高危漏洞</li>
</ul></div></div>
<div style="margin:24px 0;border:1px solid #E3F2FD;border-radius:8px;background:#FAFAFA;overflow:hidden;"><div style="display:flex;align-items:center;gap:12px;padding:12px 20px;background:linear-gradient(135deg,#E3F2FD,#BBDEFB);"><span style="width:36px;height:36px;background:#2196F3;color:#fff;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-weight:bold;font-size:16px;flex-shrink:0;">6. </span><span style="font-size:17px;font-weight:700;color:#1565C0;">回归测试</span></div><div style="padding:16px 20px;"><ul style="list-style:none;padding-left:0;margin:12px 0;">
<li style="position:relative;padding:4px 0 4px 24px;line-height:1.8;"><span style="color:#2196F3;font-weight:bold;position:absolute;left:4px;">&#9658;</span><strong>原则:</strong> 每次修改后,重跑全部用例的30%-50%</li>
<li style="position:relative;padding:4px 0 4px 24px;line-height:1.8;"><span style="color:#2196F3;font-weight:bold;position:absolute;left:4px;">&#9658;</span><strong>自动化率:</strong> 核心用例100%自动化</li>
</ul></div></div>
<div style="margin:24px 0;border:1px solid #E3F2FD;border-radius:8px;background:#FAFAFA;overflow:hidden;"><div style="display:flex;align-items:center;gap:12px;padding:12px 20px;background:linear-gradient(135deg,#E3F2FD,#BBDEFB);"><span style="width:36px;height:36px;background:#2196F3;color:#fff;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-weight:bold;font-size:16px;flex-shrink:0;">7. </span><span style="font-size:17px;font-weight:700;color:#1565C0;">冒烟测试</span></div><div style="padding:16px 20px;"><ul style="list-style:none;padding-left:0;margin:12px 0;">
<li style="position:relative;padding:4px 0 4px 24px;line-height:1.8;"><span style="color:#2196F3;font-weight:bold;position:absolute;left:4px;">&#9658;</span><strong>目标:</strong> 确认系统可运行,核心功能不崩溃</li>
<li style="position:relative;padding:4px 0 4px 24px;line-height:1.8;"><span style="color:#2196F3;font-weight:bold;position:absolute;left:4px;">&#9658;</span><strong>时间:</strong> 每次构建后10分钟内执行完</li>
</ul>
<p>> 验证做得好,Bug少一半;验证做不好,加班到天亮。</p>
<p>---</p></div></div>
## 03 确认的4个层次:穿透需求的“照妖镜”

确认比验证难10倍。因为验证有标准答案,确认没有。确认要回答“用户到底要什么”这个哲学问题。

### 第一层:需求确认
- **动作:** 测试人员提前介入需求评审
- **问题清单:**
  - 这个功能解决用户的什么痛点?
  - 用户使用场景是什么?(线上/线下、手机/PC)
  - 异常情况如何处理?(断网、超时、数据丢失)
- **案例:** 某银行APP要求“转账成功提示”,测试确认后发现用户需要的是“转账到账确认”,两者差异导致用户反复查账

### 第二层:设计确认
- **动作:** 原型评审、交互走查
- **检查点:**
  - 用户操作路径是否最短?(点击次数≤3次)
  - 错误提示是否友好?(“系统繁忙” vs “网络不通,请检查Wi-Fi”)
  - 无障碍设计是否满足?(色盲用户能否识别红色按钮)

### 第三层:用户验收测试(UAT)
- **参与人:** 真实用户、业务代表
- **流程:**
  1. 编写用户场景用例(非技术用例)
  2. 用户按场景操作并反馈
  3. 记录满意度评分(1-5分)
- **示例用例:**

场景:用户首次登录并修改密码

步骤1:打开APP,点击“登录”

步骤2:输入手机号和验证码

步骤3:系统提示“首次登录,请修改密码”

步骤4:用户输入新密码并确认

预期结果:密码修改成功,直接跳转首页

实际结果:密码修改成功,但跳转到登录页,需重新登录

问题:用户多了一步操作,满意度评分2分

text

### 第四层:上线后确认
- **方法:** A/B测试、灰度发布、用户行为分析
- **指标:**
  - 功能使用率(>50%才算成功)
  - 用户留存率(7日留存>30%)
  - 客诉率(<0.1%)
- **工具:** Google Analytics、友盟、自建埋点

<blockquote style="margin:16px 0;padding:12px 20px;background:#F5F5F5;border-left:4px solid #9E9E9E;color:#616161;font-style:italic;border-radius:0 6px 6px 0;">确认不是问用户“你要什么”,而是看用户“做了什么”。</blockquote>

---

## 04 实战:一个电商订单系统的验证与确认全流程

假设你要测试一个“订单取消”功能。看看验证和确认分别怎么做。

### 验证阶段(检查代码实现)

**需求规格:** 用户可在订单支付后30分钟内取消订单,超时不可取消。

**验证用例:**

验证1:支付后25分钟取消,应成功

def test_cancel_within_30min():

order = create_order(status='paid', create_time='2024-01-01 10:00:00')

result = cancel_order(order_id=order.id, cancel_time='2024-01-01 10:25:00')

assert result['status'] == 'success'

验证2:支付后31分钟取消,应失败

def test_cancel_after_30min():

order = create_order(status='paid', create_time='2024-01-01 10:00:00')

result = cancel_order(order_id=order.id, cancel_time='2024-01-01 10:31:00')

assert result['status'] == 'failed'

assert result['message'] == '订单已超时,无法取消'

text

**验证结果:** 代码实现正确,边界值处理到位。

### 确认阶段(检查用户需求)

**用户场景:**
- 场景1:用户下错单(数量、颜色、地址错误)
- 场景2:用户发现更优惠的商品
- 场景3:用户付款后立刻后悔

**确认问题:**
1. “30分钟”这个时间是否符合用户预期?(用户调查:62%用户希望15分钟内可取消)
2. 取消后能否恢复?(用户需求:取消后30分钟内可恢复)
3. 取消后退款到账时间?(用户期望:即时到账,实际:T+1)

**确认结果:**
- 30分钟太长,需要缩短到15分钟
- 增加“取消恢复”功能
- 优化退款流程,改为即时到账

<blockquote style="margin:16px 0;padding:12px 20px;background:#F5F5F5;border-left:4px solid #9E9E9E;color:#616161;font-style:italic;border-radius:0 6px 6px 0;">验证通过不代表产品可用,确认通过才是。</blockquote>

---

## 05 测试工程师的进阶之路:从验证者到确认者

大多数测试工程师卡在“验证”阶段。要成为高级测试专家,必须跨越到“确认”。

### 能力差距对比

| 级别 | 验证能力 | 确认能力 | 年薪范围 |
|------|----------|----------|----------|
| 初级(1-3年) | 90% | 10% | 15-25万 |
| 中级(3-5年) | 70% | 30% | 25-40万 |
| 高级(5-10年) | 30% | 70% | 40-70万 |
| 专家(10年+) | 10% | 90% | 70万+ |

### 进阶三步法

**第一步:改变提问方式**
- 不要说“用例覆盖率100%”,要说“用户场景覆盖100%”
- 不要说“功能通过”,要说“用户满意”

**第二步:参与产品设计**
- 每周参加产品评审会
- 主动提出“这个设计用户会用吗”
- 建立用户反馈收集机制

**第三步:建立确认体系**
- 定义用户满意度指标(CSAT、NPS)
- 创建用户行为分析仪表盘
- 定期做用户访谈(每月至少10个)

**代码示例:确认自动化工具**

简单的用户行为分析脚本

import pandas as pd

def analyze_user_behavior(log_file):

df = pd.read_csv(log_file)

计算功能使用率

feature_usage = df.groupby('feature')['user_id'].nunique()

total_users = df['user_id'].nunique()

usage_rate = feature_usage / total_users * 100

找出使用率低于20%的功能

low_usage_features = usage_rate[usage_rate < 20]

print(f"低使用率功能:{list(low_usage_features.index)}")

计算用户流失点

df['session_end'] = df.groupby('user_id')['timestamp'].diff().shift(-1)

drop_off_points = df[df['session_end'] > 300] # 超过5分钟无操作

print(f"用户流失点:{drop_off_points['page'].value_counts()}")

相关问题

软件测试中的验证与确认有什么区别_千锋教育

7软件测试基础知识点,新手必须掌握_千锋教育

缺陷生命周期:从发现Bug到关闭Bug的全过程_千锋教育

3年软件测试基础知识学习路线图_千锋教育

软件测试中的验证与确认有什么区别_千锋教育

缺陷生命周期:从发现Bug到关闭Bug的全过程_千锋教育