软件测试与软件质量——缺陷
从软件测试的基本概念出发,系统讲解软件质量模型、缺陷管理、测试级别、测试类型、测试方法、测试用例设计与测试工具。
🎯学习目标
- 理解软件测试的定义、目的与基本原则;
- 掌握软件质量模型(McCall、ISO 9126、ISO 25010)及质量属性;
- 理解质量保证(QA)与质量控制(QC)的区别与联系;
- 掌握缺陷分类、缺陷生命周期、缺陷报告与缺陷分析方法;
- 掌握四级测试级别:单元测试、集成测试、系统测试、验收测试;
- 了解主要测试类型:功能测试、性能测试、安全测试、兼容性测试;
- 掌握三种测试方法:黑盒测试、白盒测试、灰盒测试;
- 掌握测试用例设计技术:等价类划分、边界值分析、因果图、决策表;
- 了解常用测试工具及其适用场景。
1软件测试概述
什么是软件测试
软件测试(Software Testing)是为了发现软件产品中的缺陷(Bug)而执行程序的过程。更正式地说:
软件测试就像"找茬游戏"——把软件运行起来,看看它有没有"做错事"或"没做到位"的地方。
测试不是证明软件"没有问题",而是尽可能地暴露问题。正如著名测试专家 Glenford Myers 所说:"测试是为了发现错误而执行程序的过程。"
测试的目的
发现缺陷
尽可能多地发现软件中的缺陷,尤其是严重的缺陷。测试的直接目标就是"找 Bug"。
验证需求
验证软件是否满足需求规格说明中定义的功能和非功能需求,确保"做了对的事"。
评估质量
通过测试收集数据,评估软件的质量水平,为发布决策提供依据。
- 测试是为了发现错误而执行程序的过程;
- 好的测试方案是发现尚未发现的错误的可能性很大;
- 成功的测试是发现了至今未发现的错误的测试。
测试的基本原则
| 原则 | 说明 |
|---|---|
| 1. 测试显示缺陷存在 | 测试可以证明缺陷存在,但不能证明缺陷不存在。即使测试没有发现缺陷,也不能证明软件是完全正确的。 |
| 2. 穷尽测试不可能 | 除了非常小的系统,对所有可能的输入和执行路径进行完全测试是不现实的。需要运用风险分析和优先级来决定测试重点。 |
| 3. 测试尽早介入 | 越早发现缺陷,修复成本越低。需求阶段发现 Bug 的修复成本是编码阶段的1/100。 |
| 4. 缺陷聚集性 | 少量模块通常包含大部分缺陷(80/20 法则——80% 的缺陷集中在 20% 的模块中)。 |
| 5. 杀虫剂悖论 | 同样的测试用例反复使用,将不再能发现新缺陷。需要定期review 和更新测试用例。 |
| 6. 测试依赖上下文 | 不同类型的软件(游戏 vs 飞控系统)需要不同的测试策略和方法。 |
| 7. 无错误谬误 | 发现并修复大量缺陷不代表系统可用。如果系统不是用户所需要的,那它再"正确"也毫无意义。 |
2软件质量
什么是软件质量
软件质量是指软件产品满足规定的和隐含需求的能力的特性总和。简单来说:质量 = 满足需求的程度。
质量模型
质量模型是将软件质量特性层次化分解的框架。经典的质量模型有三个:
| 模型 | 年代 | 层次结构 | 特点 |
|---|---|---|---|
| McCall 模型 | 1977 | 因素 → 准则 → 度量 | 最早的质量模型,从产品运行、修正、转移三个角度分析 |
| ISO 9126 | 1991/2001 | 特性 → 子特性 | 国际标准,定义 6 大质量特性和 27 个子特性 |
| ISO 25010 | 2011 | 特性 → 子特性 | ISO 9126 的升级版,新增安全性、兼容性等,8 大特性 |
ISO 9126 六大质量特性 ⭐
功能性
Functionality可靠性
Reliability效率
Efficiency易用性
Usability可维护性
Maintainability可移植性
Portability质量保证 vs 质量控制 ⭐
| 对比维度 | 质量保证(QA) | 质量控制(QC) |
|---|---|---|
| 定义 | 为确保软件开发过程的质量而采取的预防性活动 | 为发现和修复缺陷而采取的检测性活动 |
| 关注点 | 过程——做事的方式对不对 | 产品——做出的东西对不对 |
| 时机 | 贯穿整个开发过程(事前预防) | 主要在编码完成后(事后检测) |
| 手段 | 制定标准、流程审计、技术评审、培训 | 测试、代码审查、走查、调试 |
| 主动性 | 主动——预防缺陷产生 | 被动——发现已存在的缺陷 |
| 类比 | 像"打疫苗"——预防疾病 | 像"体检"——发现疾病 |
3缺陷管理
什么是软件缺陷
软件缺陷(Bug/Defect)是指软件产品中存在的问题,导致软件不能满足用户需求或预期结果。
缺陷分类
| 分类维度 | 类别 | 说明 |
|---|---|---|
| 严重程度 | 致命(Blocker) | 系统崩溃、数据丢失、安全漏洞,导致软件完全无法使用 |
| 严重(Critical) | 主要功能不可用、性能严重下降 | |
| 一般(Major) | 次要功能有问题、界面显示错误 | |
| 轻微(Minor) | 界面布局不美观、提示信息不准确 | |
| 建议(Suggestion) | 改善建议,非真正缺陷 | |
| 优先级 | 高(High) | 必须立即修复,阻塞测试或发布 |
| 中(Medium) | 在当前版本发布前修复 | |
| 低(Low) | 可以推迟到后续版本修复 | |
| 缺陷类型 | 功能缺陷 | 功能不符合需求 |
| 界面缺陷 | UI 布局、样式、交互问题 | |
| 性能缺陷 | 响应慢、资源占用高 | |
| 安全缺陷 | SQL 注入、XSS、权限绕过等 |
缺陷生命周期 ⭐
缺陷报告
一份好的缺陷报告应该包含以下要素:
| 字段 | 说明 | 示例 |
|---|---|---|
| 缺陷ID | 唯一标识符 | BUG-2024-001 |
| 标题 | 简明扼要描述问题 | "登录页面输入错误密码后无提示" |
| 严重程度 | 致命/严重/一般/轻微/建议 | 一般 |
| 优先级 | 高/中/低 | 高 |
| 重现步骤 | 详细的操作步骤(最重要) | 1. 打开登录页 → 2. 输入正确用户名 → 3. 输入错误密码 → 4. 点击登录 |
| 预期结果 | 应该发生什么 | "提示'密码错误,请重新输入'" |
| 实际结果 | 实际发生了什么 | "无任何提示,页面卡住" |
| 环境信息 | 操作系统、浏览器、版本等 | Chrome 120, Windows 11 |
| 附件 | 截图、录屏、日志 | screenshot.png |
缺陷分析方法
缺陷分布分析
Defect Distribution缺陷趋势分析
Defect Trend因果图
Cause-Effect帕累托分析
Pareto (80/20)4测试级别 ⭐
测试级别按照测试范围由小到大,分为四个层次,对应软件开发的不同阶段:
单元测试(Unit Testing)⭐
什么是单元测试
针对软件中最小可测试单元(函数、方法、类)进行的测试。通常由开发人员在编码阶段完成。
测试内容
模块接口(输入输出)、局部数据结构、边界条件、独立路径、错误处理。通常使用白盒测试方法。
驱动模块(Driver):模拟调用被测模块的上层模块;桩模块(Stub):模拟被测模块调用的下层模块。
集成测试(Integration Testing)
在单元测试基础上,将模块组装起来测试接口的正确性。重点检查模块间的数据传递和协作。
| 策略 | 说明 | 优缺点 |
|---|---|---|
| 大爆炸集成 | 所有模块一次性组装测试 | 简单快速;但出错难定位 |
| 自顶向下 | 从主控模块开始,逐层向下集成(用桩模块) | 早期验证主流程;但底层测试晚 |
| 自底向上 | 从底层模块开始,逐层向上集成(用驱动模块) | 底层模块充分测试;但顶层测试晚 |
| 三明治集成 | 结合自顶向下和自底向上,两头向中间集成 | 兼顾优缺点,但复杂度高 |
系统测试(System Testing)
将整个软件系统作为整体,在真实或模拟的运行环境下进行全面测试。由独立测试团队执行。
功能测试
验证系统功能是否符合需求规格说明
非功能测试
性能、安全、兼容性、可靠性等
回归测试
修改后重新测试,确保没有引入新缺陷
验收测试(Acceptance Testing)
由用户/客户参与,验证系统是否满足合同或业务需求,决定是否接受系统。
| 类型 | 执行者 | 目的 |
|---|---|---|
| α 测试 | 用户在开发方场所 | 在受控环境下让用户试用,收集反馈 |
| β 测试 | 用户在自己场所 | 在真实环境下让用户自由使用,发现更多问题 |
| UAT 测试 | 客户方测试人员 | 按照验收标准逐项验证,作为上线依据 |
5测试类型
功能测试
验证软件的每个功能是否按照需求规格说明正常工作。是最基本、最重要的测试类型。
- 冒烟测试(Smoke Test):快速验证核心功能是否可用,决定是否值得进行深入测试
- 回归测试(Regression Test):修改代码后重新执行测试,确保没有引入新的 Bug
- 探索性测试(Exploratory Test):边学习、边设计、边执行、边评估,灵活发现缺陷
性能测试
评估系统在特定负载下的响应时间、吞吐量、资源利用率等性能指标。
负载测试
Load Test压力测试
Stress Test稳定性测试
Soak Test安全测试
发现系统中的安全漏洞,防止数据泄露、非法访问、恶意攻击。
| 测试项 | 说明 | 示例 |
|---|---|---|
| SQL 注入 | 通过输入恶意 SQL 片段获取数据库数据 | 输入 ' OR 1=1 -- 绕过登录 |
| XSS 攻击 | 在页面中注入恶意脚本 | 输入 <script>alert(1)</script> |
| 权限绕过 | 普通用户访问管理员功能 | 修改 URL 参数访问他人数据 |
| 数据加密 | 敏感数据是否加密传输和存储 | 密码是否明文传输 |
兼容性测试
验证软件在不同操作系统、浏览器、设备、分辨率下能否正常工作。
浏览器兼容
Chrome、Firefox、Safari、Edge 等主流浏览器,包括不同版本
设备兼容
手机、平板、PC、不同分辨率、不同操作系统(Windows/macOS/Linux/iOS/Android)
6测试方法 ⭐
黑盒测试(Black-Box Testing)⭐
不关心内部代码结构,只关注输入和输出。把软件当作一个"黑盒子"——给它输入,检查输出是否正确。
优点
从用户角度测试,不需要了解代码;能发现功能遗漏、接口错误、数据结构错误
缺点
无法测试所有输入组合(穷举不可能);代码内部逻辑错误可能遗漏
适用场景:系统测试、验收测试、功能测试。
白盒测试(White-Box Testing)⭐
基于代码内部结构来设计测试用例。测试人员需要了解代码逻辑,确保每条语句、每个分支都被执行到。
| 覆盖类型 | 说明 | 覆盖强度 |
|---|---|---|
| 语句覆盖 | 每条可执行语句至少执行一次 | ⭐ 最弱 |
| 判定覆盖(分支覆盖) | 每个判定的真假分支至少各执行一次 | ⭐⭐ |
| 条件覆盖 | 每个判定中每个条件的真假值至少各取一次 | ⭐⭐ |
| 判定-条件覆盖 | 同时满足判定覆盖和条件覆盖 | ⭐⭐⭐ |
| 条件组合覆盖 | 每个判定中各条件的真假组合至少出现一次 | ⭐⭐⭐⭐ |
| 路径覆盖 | 覆盖程序中所有可能的执行路径 | ⭐⭐⭐⭐⭐ 最强 |
if (A > 0 && B > 0) {
C = A + B; // 语句1
}
// 语句覆盖:只需 A=1, B=1 → 走"真"分支,执行语句1
// 判定覆盖:需要两组:A=1,B=1(真)和 A=-1,B=1(假)
// 条件覆盖:A>0为真/假 + B>0为真/假,至少两组用例
// 路径覆盖:同判定覆盖(本例只有两条路径)
灰盒测试(Gray-Box Testing)
介于黑盒与白盒之间——既关注输入输出,也关注部分内部逻辑。通常用于集成测试,了解模块间接口和数据流。
| 方法 | 关注点 | 了解代码适用级别 | |
|---|---|---|---|
| 黑盒 | 输入 → 输出 | 不需要 | 系统/验收测试 |
| 白盒 | 代码逻辑、路径 | 需要 | 单元测试 |
| 灰盒 | 接口 + 数据流 | 部分了解 | 集成测试 |
7测试用例设计 ⭐
等价类划分 ⭐
将输入数据划分为若干等价类,从每个类中选取一个代表性值作为测试用例。假设同一等价类中的数据具有相同的测试效果。
有效等价类
无效等价类
需求:某程序输入月份(1-12的整数),输出该月天数。
等价类划分:
| 等价类 | 范围 | 类型 | 代表值 |
|---|---|---|---|
| 28天月(非闰年2月) | {2} | 有效 | 2 |
| 30天月 | {4,6,9,11} | 有效 | 4 |
| 31天月 | {1,3,5,7,8,10,12} | 有效 | 1 |
| 小于1 | {0, -1, ...} | 无效 | 0 |
| 大于12 | {13, 14, ...} | 无效 | 13 |
| 非整数 | {1.5, "abc", ...} | 无效 | 1.5 |
边界值分析 ⭐
大量的缺陷发生在输入/输出范围的边界上,而非内部。边界值分析选取边界及其附近的值作为测试用例。
需求:输入范围 [1, 100] 的整数。
边界值测试用例:
| 边界 | 测试值 | 说明 |
|---|---|---|
| 最小值 | 0, 1, 2 | 刚好低于下界、下界、刚好高于下界 |
| 最大值 | 99, 100, 101 | 刚好低于上界、上界、刚好高于上界 |
记忆口诀:"边界值取五个点——min-1, min, min+1, max-1, max, max+1"
因果图
当输入条件之间有约束关系时,用因果图来分析输入条件(因)和输出结果(果)之间的逻辑关系,再生成测试用例。
| 符号 | 含义 | 说明 |
|---|---|---|
| 恒等 | 若 C1=1,则 E1=1 | 输入为真,输出必为真 |
| 非 | 若 C1=1,则 E1=0 | 输入为真,输出为假 |
| 或 | 若 C1 或 C2 任一为 1,则 E1=1 | 多个输入满足一个即可 |
| 与 | 若 C1 和 C2 都为 1,则 E1=1 | 多个输入全部满足才行 |
决策表(判定表)⭐
决策表是因果图的"表格版",适合处理多条件组合的场景。清晰列出所有条件组合及其对应动作。
需求:某电商优惠规则——VIP 且消费满 500 打 8 折;VIP 且不满 500 打 9 折;非 VIP 无折扣。
| 条件 | 规则 | |||||
|---|---|---|---|---|---|---|
| 条件项 | 取值 | R1 | R2 | R3 | ||
| 是否 VIP? | Y/N | Y | Y | N | ||
| 消费 ≥ 500? | Y/N | Y | N | — | ||
| 动作 | ||||||
| 打 8 折 | ✓ | |||||
| 打 9 折 | ✓ | |||||
| 无折扣 | ✓ | |||||
设计步骤:① 确定所有条件 → ② 确定所有动作 → ③ 列出条件取值组合 → ④ 填写每种组合对应的动作 → ⑤ 每一列就是一个测试用例。
8测试工具
自动化测试工具
| 工具 | 类型 | 适用场景 |
|---|---|---|
| Selenium | Web UI 自动化 | 浏览器自动化测试,支持多语言(Java/Python/C#) |
| Appium | 移动端自动化 | Android/iOS 应用自动化测试 |
| Cypress | Web 端到端测试 | 现代 Web 应用,速度快、调试友好 |
| Playwright | Web 自动化 | 微软出品,支持 Chromium/Firefox/WebKit |
| JMeter | 接口/性能测试 | HTTP 接口测试、负载测试 |
| Postman | API 测试 | RESTful API 手动/自动化测试 |
单元测试框架
| 语言 | 框架 | 特点 |
|---|---|---|
| Java | JUnit / TestNG | 最流行的 Java 单元测试框架,注解驱动 |
| Python | pytest | 简洁语法、丰富插件生态 |
| JavaScript | Jest / Mocha | React 生态标配,快照测试 |
| C++ | Google Test | 谷歌出品,跨平台 |
| C# | xUnit / NUnit | .NET 生态标配 |
性能测试工具
JMeter
Apache 开源,支持 HTTP、数据库、FTP 等协议的负载测试。GUI 操作 + 脚本化。
LoadRunner
Micro Focus 商业工具,支持大规模并发测试,企业级性能测试方案。
Locust
Python 编写的负载测试工具,用代码定义用户行为,分布式支持。
测试管理工具
| 工具 | 功能 |
|---|---|
| JIRA | 项目管理 + 缺陷跟踪,最流行的敏捷工具 |
| TestLink | 测试用例管理、测试计划、测试执行跟踪 |
| Bugzilla | 开源缺陷跟踪系统,Mozilla 出品 |
| 禅道 | 国产项目管理工具,集需求/缺陷/测试管理于一体 |
| SonarQube | 代码质量检测平台,支持 20+ 语言的静态分析 |
⭐重点例题
需求:某程序输入三个整数 a、b、c,分别作为三角形的三条边,判断能否构成三角形。若能,判断是等边、等腰还是一般三角形。
分析:
- 等价类划分:
- 有效等价类:能构成三角形(a+b>c 且 a+c>b 且 b+c>a)
- 无效等价类:不能构成三角形(如 1,2,5)
- 测试用例:
| 编号 | 输入 (a,b,c) | 等价类 | 预期输出 |
|---|---|---|---|
| 1 | 3, 4, 5 | 有效:一般三角形 | 一般三角形 |
| 2 | 3, 3, 3 | 有效:等边三角形 | 等边三角形 |
| 3 | 3, 3, 4 | 有效:等腰三角形 | 等腰三角形 |
| 4 | 1, 2, 5 | 无效:不能构成 | "不能构成三角形" |
| 5 | 0, 3, 4 | 无效:边 ≤ 0 | "输入非法" |
| 6 | -1, 3, 4 | 无效:负数 | "输入非法" |
代码:
1: int foo(int a, int b) {
2: int x = 0;
3: if (a > 0) { // 判定1
4: x = x + 1;
5: }
6: if (b > 0) { // 判定2
7: x = x + 2;
8: }
9: return x;
10: }
问题:设计测试用例分别满足语句覆盖、判定覆盖、路径覆盖。
解答:
| 覆盖类型 | 测试用例 | 说明 |
|---|---|---|
| 语句覆盖 | a=1, b=1 | 执行所有语句(行3-8全部执行) |
| 判定覆盖 | ① a=1,b=1 ② a=-1,b=-1 | ① 判定1真+判定2真 ② 判定1假+判定2假 |
| 路径覆盖 | ① a=1,b=1 ② a=1,b=-1 ③ a=-1,b=1 ④ a=-1,b=-1 | 覆盖全部 4 条路径(2个判定×2种结果=4路径) |
需求:某银行贷款审批规则:
- 年龄≥18 且 信用良好 且 有担保 → 批准贷款
- 年龄≥18 且 信用良好 且 无担保 → 需人工审核
- 年龄≥18 且 信用不良 → 拒绝
- 年龄<18 → 拒绝
| 条件\规则 | R1 | R2 | R3 | R4 |
|---|---|---|---|---|
| 年龄≥18? | Y | Y | Y | N |
| 信用良好? | Y | Y | N | — |
| 有担保? | Y | N | — | — |
| 批准贷款 | ✓ | |||
| 人工审核 | ✓ | |||
| 拒绝 | ✓ | ✓ |
测试用例:每条规则对应一个测试用例,共 4 个。
🎯自测(点击展开)
软件测试的目的是什么?
QA 和 QC 的区别是什么?
缺陷的严重程度和优先级有什么区别?
四级测试级别分别由谁执行?
黑盒测试和白盒测试的核心区别是什么?
等价类划分的原理是什么?
什么是边界值分析?为什么要关注边界?
回归测试是什么?什么时候需要?
📝强化题库
选择题点选即时判分;填空题输入后"检查"或"显示答案"。