🎓 总站 🏠 本课目录 01 概述 02 软件过程 03 需求工程 04 系统建模 05 概要设计 06 报告与高可信 07 交互与状态图 08 详细设计 10 测试与质量
软件系统综合课程设计 · 第10章

软件测试与软件质量——缺陷

从软件测试的基本概念出发,系统讲解软件质量模型、缺陷管理、测试级别、测试类型、测试方法、测试用例设计与测试工具。

📚 学习进度
0%

🎯学习目标

  • 理解软件测试的定义、目的与基本原则;
  • 掌握软件质量模型(McCall、ISO 9126、ISO 25010)及质量属性;
  • 理解质量保证(QA)与质量控制(QC)的区别与联系;
  • 掌握缺陷分类、缺陷生命周期、缺陷报告与缺陷分析方法;
  • 掌握四级测试级别:单元测试、集成测试、系统测试、验收测试;
  • 了解主要测试类型:功能测试、性能测试、安全测试、兼容性测试;
  • 掌握三种测试方法:黑盒测试、白盒测试、灰盒测试;
  • 掌握测试用例设计技术:等价类划分、边界值分析、因果图、决策表;
  • 了解常用测试工具及其适用场景。

1软件测试概述

什么是软件测试

软件测试(Software Testing)是为了发现软件产品中的缺陷(Bug)而执行程序的过程。更正式地说:

⭐ IEEE 定义软件测试是使用人工或自动手段来运行或测试某个系统的过程,其目的在于检验它是否满足规定的需求或弄清预期结果与实际结果之间的差别。
💡 通俗理解

软件测试就像"找茬游戏"——把软件运行起来,看看它有没有"做错事"或"没做到位"的地方。

测试不是证明软件"没有问题",而是尽可能地暴露问题。正如著名测试专家 Glenford Myers 所说:"测试是为了发现错误而执行程序的过程。"

测试的目的

🐛

发现缺陷

尽可能多地发现软件中的缺陷,尤其是严重的缺陷。测试的直接目标就是"找 Bug"。

验证需求

验证软件是否满足需求规格说明中定义的功能和非功能需求,确保"做了对的事"。

📊

评估质量

通过测试收集数据,评估软件的质量水平,为发布决策提供依据。

💡 Myers 的三个重要观点
  1. 测试是为了发现错误而执行程序的过程;
  2. 好的测试方案是发现尚未发现的错误的可能性很大;
  3. 成功的测试是发现了至今未发现的错误的测试。

测试的基本原则

原则说明
1. 测试显示缺陷存在测试可以证明缺陷存在,但不能证明缺陷不存在。即使测试没有发现缺陷,也不能证明软件是完全正确的。
2. 穷尽测试不可能除了非常小的系统,对所有可能的输入和执行路径进行完全测试是不现实的。需要运用风险分析优先级来决定测试重点。
3. 测试尽早介入越早发现缺陷,修复成本越低。需求阶段发现 Bug 的修复成本是编码阶段的1/100
4. 缺陷聚集性少量模块通常包含大部分缺陷(80/20 法则——80% 的缺陷集中在 20% 的模块中)。
5. 杀虫剂悖论同样的测试用例反复使用,将不再能发现新缺陷。需要定期review 和更新测试用例。
6. 测试依赖上下文不同类型的软件(游戏 vs 飞控系统)需要不同的测试策略和方法。
7. 无错误谬误发现并修复大量缺陷不代表系统可用。如果系统不是用户所需要的,那它再"正确"也毫无意义。
修复成本(相对值) 开发阶段 需求 设计 编码 测试 发布后 1x 5x 10x 50x 100x 1x 5x 10x 50x 100x
图1 · 缺陷修复成本随阶段呈指数增长——越早发现越便宜

2软件质量

什么是软件质量

软件质量是指软件产品满足规定的和隐含需求的能力的特性总和。简单来说:质量 = 满足需求的程度

💡 通俗理解质量就像"体检报告"——通过多个指标(功能、性能、安全、易用性……)综合评估软件的"健康程度"。一个软件功能再强,如果经常崩溃、响应慢、不安全,那它的质量就不高。

质量模型

质量模型是将软件质量特性层次化分解的框架。经典的质量模型有三个:

模型年代层次结构特点
McCall 模型1977因素 → 准则 → 度量最早的质量模型,从产品运行、修正、转移三个角度分析
ISO 91261991/2001特性 → 子特性国际标准,定义 6 大质量特性和 27 个子特性
ISO 250102011特性 → 子特性ISO 9126 的升级版,新增安全性、兼容性等,8 大特性

ISO 9126 六大质量特性 ⭐

⚙️

功能性

Functionality
软件满足功能需求的能力。包含:适合性、准确性、互操作性、安全保密性、功能依从性。

可靠性

Reliability
在规定条件和时间内完成规定功能的能力。包含:成熟性(故障频率)、容错性、易恢复性、可靠性依从性。
🚀

效率

Efficiency
在规定条件下相对于资源使用的性能水平。包含:时间特性(响应时间)、资源利用性(CPU/内存占用)、效率依从性。
📱

易用性

Usability
用户使用软件时的满意程度和效率。包含:易理解性、易学性、易操作性、吸引性、易用依从性。
🔄

可维护性

Maintainability
对软件进行修改的容易程度。包含:易分析性、易改变性、稳定性、易测试性、可维护依从性。
🌐

可移植性

Portability
软件从一个环境迁移到另一个环境的能力。包含:适应性、易安装性、易替换性、可共存性、可移植依从性。

质量保证 vs 质量控制 ⭐

对比维度质量保证(QA)质量控制(QC)
定义为确保软件开发过程的质量而采取的预防性活动为发现和修复缺陷而采取的检测性活动
关注点过程——做事的方式对不对产品——做出的东西对不对
时机贯穿整个开发过程(事前预防主要在编码完成后(事后检测
手段制定标准、流程审计、技术评审、培训测试、代码审查、走查、调试
主动性主动——预防缺陷产生被动——发现已存在的缺陷
类比像"打疫苗"——预防疾病像"体检"——发现疾病
⭐ QA vs QC 口诀QA 管过程,QC 管产品;QA 预防,QC 检测;QA 是"不让你生病",QC 是"给你看病"。两者相辅相成,缺一不可。

3缺陷管理

什么是软件缺陷

软件缺陷(Bug/Defect)是指软件产品中存在的问题,导致软件不能满足用户需求或预期结果。

💡 缺陷的通俗理解缺陷就是软件"做错了"或"没做到"的地方。比如:点击按钮没反应、计算结果错误、页面打不开、数据丢失等。

缺陷分类

分类维度类别说明
严重程度致命(Blocker)系统崩溃、数据丢失、安全漏洞,导致软件完全无法使用
严重(Critical)主要功能不可用、性能严重下降
一般(Major)次要功能有问题、界面显示错误
轻微(Minor)界面布局不美观、提示信息不准确
建议(Suggestion)改善建议,非真正缺陷
优先级高(High)必须立即修复,阻塞测试或发布
中(Medium)在当前版本发布前修复
低(Low)可以推迟到后续版本修复
缺陷类型功能缺陷功能不符合需求
界面缺陷UI 布局、样式、交互问题
性能缺陷响应慢、资源占用高
安全缺陷SQL 注入、XSS、权限绕过等
⭐ 严重程度 vs 优先级(易混淆)严重程度是缺陷对系统的影响有多大(客观属性);优先级是缺陷需要多快被修复(主观决策)。一个"界面公司名写错"的缺陷严重程度低,但优先级可能是高(领导要求马上改)。

缺陷生命周期 ⭐

新建 New 确认 Confirmed 拒绝 Rejected 修复中 Fixing 已修复 Fixed 重新打开 Reopen 已验证 Verified 确认缺陷 不是缺陷 分配修复 测试通过 测试未通过 关闭 回归缺陷
图2 · 缺陷生命周期:新建 → 确认 → 修复中 → 已修复 → 验证 → 关闭;验证失败则重新打开

缺陷报告

一份好的缺陷报告应该包含以下要素:

字段说明示例
缺陷ID唯一标识符BUG-2024-001
标题简明扼要描述问题"登录页面输入错误密码后无提示"
严重程度致命/严重/一般/轻微/建议一般
优先级高/中/低
重现步骤详细的操作步骤(最重要)1. 打开登录页 → 2. 输入正确用户名 → 3. 输入错误密码 → 4. 点击登录
预期结果应该发生什么"提示'密码错误,请重新输入'"
实际结果实际发生了什么"无任何提示,页面卡住"
环境信息操作系统、浏览器、版本等Chrome 120, Windows 11
附件截图、录屏、日志screenshot.png

缺陷分析方法

📊

缺陷分布分析

Defect Distribution
分析缺陷在不同模块、不同严重程度、不同开发阶段的分布情况。找出"重灾区"模块,集中力量改善。
📈

缺陷趋势分析

Defect Trend
跟踪缺陷发现数和修复数随时间的变化趋势。当发现数持续下降、修复数追上发现数时,说明软件趋于稳定。
🐟

因果图

Cause-Effect
分析缺陷的根本原因(Root Cause),如需求不清、设计缺陷、编码错误、环境问题等,从源头预防同类缺陷。
🍕

帕累托分析

Pareto (80/20)
按缺陷类型或模块进行排序统计,找到贡献了80%缺陷的20%原因,优先解决高频原因。

4测试级别 ⭐

测试级别按照测试范围由小到大,分为四个层次,对应软件开发的不同阶段:

单元测试 开发人员 · 最小单元 集成测试 开发/测试 · 模块接口 系统测试 测试团队 · 整个系统 验收测试 用户/客户 · 验收确认 数量多 范围小 数量少 范围大
图3 · 四级测试级别——从下到上范围越来越大,数量越来越少

单元测试(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
在正常负载下长时间运行(24h~72h),检测内存泄漏、资源耗尽等长期问题。

安全测试

发现系统中的安全漏洞,防止数据泄露、非法访问、恶意攻击。

测试项说明示例
SQL 注入通过输入恶意 SQL 片段获取数据库数据输入 ' OR 1=1 -- 绕过登录
XSS 攻击在页面中注入恶意脚本输入 <script>alert(1)</script>
权限绕过普通用户访问管理员功能修改 URL 参数访问他人数据
数据加密敏感数据是否加密传输和存储密码是否明文传输

兼容性测试

验证软件在不同操作系统、浏览器、设备、分辨率下能否正常工作。

💻

浏览器兼容

Chrome、Firefox、Safari、Edge 等主流浏览器,包括不同版本

📱

设备兼容

手机、平板、PC、不同分辨率、不同操作系统(Windows/macOS/Linux/iOS/Android)

6测试方法 ⭐

黑盒测试 白盒测试 灰盒测试 灰盒 灰盒
图4 · 三种测试方法的关系——灰盒是黑盒与白盒的结合

黑盒测试(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-150"中,有效等价类为 [1, 150] 内的整数。

无效等价类

不符合规格说明的非法输入。如"年龄1-150"中,无效等价类为 <1 和 >150 的值。
等价类划分示例

需求:某程序输入月份(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 无折扣。

条件规则
条件项取值R1R2R3
是否 VIP?Y/NYYN
消费 ≥ 500?Y/NYN
动作
打 8 折
打 9 折
无折扣

设计步骤:① 确定所有条件 → ② 确定所有动作 → ③ 列出条件取值组合 → ④ 填写每种组合对应的动作 → ⑤ 每一列就是一个测试用例。

8测试工具

自动化测试工具

工具类型适用场景
SeleniumWeb UI 自动化浏览器自动化测试,支持多语言(Java/Python/C#)
Appium移动端自动化Android/iOS 应用自动化测试
CypressWeb 端到端测试现代 Web 应用,速度快、调试友好
PlaywrightWeb 自动化微软出品,支持 Chromium/Firefox/WebKit
JMeter接口/性能测试HTTP 接口测试、负载测试
PostmanAPI 测试RESTful API 手动/自动化测试

单元测试框架

语言框架特点
JavaJUnit / TestNG最流行的 Java 单元测试框架,注解驱动
Pythonpytest简洁语法、丰富插件生态
JavaScriptJest / MochaReact 生态标配,快照测试
C++Google Test谷歌出品,跨平台
C#xUnit / NUnit.NET 生态标配

性能测试工具

🔥

JMeter

Apache 开源,支持 HTTP、数据库、FTP 等协议的负载测试。GUI 操作 + 脚本化。

🚀

LoadRunner

Micro Focus 商业工具,支持大规模并发测试,企业级性能测试方案。

Locust

Python 编写的负载测试工具,用代码定义用户行为,分布式支持。

测试管理工具

工具功能
JIRA项目管理 + 缺陷跟踪,最流行的敏捷工具
TestLink测试用例管理、测试计划、测试执行跟踪
Bugzilla开源缺陷跟踪系统,Mozilla 出品
禅道国产项目管理工具,集需求/缺陷/测试管理于一体
SonarQube代码质量检测平台,支持 20+ 语言的静态分析

重点例题

例题1:等价类划分与边界值分析

需求:某程序输入三个整数 a、b、c,分别作为三角形的三条边,判断能否构成三角形。若能,判断是等边、等腰还是一般三角形。

分析:

  • 等价类划分:
    • 有效等价类:能构成三角形(a+b>c 且 a+c>b 且 b+c>a)
    • 无效等价类:不能构成三角形(如 1,2,5)
  • 测试用例:
编号输入 (a,b,c)等价类预期输出
13, 4, 5有效:一般三角形一般三角形
23, 3, 3有效:等边三角形等边三角形
33, 3, 4有效:等腰三角形等腰三角形
41, 2, 5无效:不能构成"不能构成三角形"
50, 3, 4无效:边 ≤ 0"输入非法"
6-1, 3, 4无效:负数"输入非法"
例题2:白盒覆盖

代码:

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路径)
例题3:决策表设计

需求:某银行贷款审批规则:

  • 年龄≥18 且 信用良好 且 有担保 → 批准贷款
  • 年龄≥18 且 信用良好 且 无担保 → 需人工审核
  • 年龄≥18 且 信用不良 → 拒绝
  • 年龄<18 → 拒绝
条件\规则R1R2R3R4
年龄≥18?YYYN
信用良好?YYN
有担保?YN
批准贷款
人工审核
拒绝

测试用例:每条规则对应一个测试用例,共 4 个。

🎯自测(点击展开)

软件测试的目的是什么?
发现软件中的缺陷、验证需求是否被正确实现、评估软件质量水平。测试不是证明软件没有问题,而是尽可能暴露问题。
QA 和 QC 的区别是什么?
QA(质量保证)关注过程,通过预防手段确保质量;QC(质量控制)关注产品,通过检测手段发现缺陷。QA 是"预防",QC 是"检测"。
缺陷的严重程度和优先级有什么区别?
严重程度是缺陷对系统的客观影响(致命/严重/一般/轻微);优先级是需要多快修复的主观决策(高/中/低)。一个界面错误可能严重程度低但优先级高。
四级测试级别分别由谁执行?
单元测试由开发人员执行;集成测试由开发/测试人员执行;系统测试由独立测试团队执行;验收测试由用户/客户执行。
黑盒测试和白盒测试的核心区别是什么?
黑盒不关心内部代码,只关注输入输出(功能视角);白盒基于代码内部结构设计用例(结构视角)。黑盒用于系统测试,白盒用于单元测试。
等价类划分的原理是什么?
将输入数据划分为若干等价类,假设同一类中数据的测试效果相同,从每个类中选一个代表性值作为测试用例。分为有效等价类和无效等价类。
什么是边界值分析?为什么要关注边界?
选取输入/输出范围边界及其附近的值作为测试用例。因为大量缺陷发生在边界上(如循环条件、范围判断),常见的取 min-1, min, min+1, max-1, max, max+1。
回归测试是什么?什么时候需要?
修改代码后重新执行测试,确保没有引入新缺陷、原有功能未被破坏。在每次代码修改、Bug 修复、新功能添加后都需要进行回归测试。

📝强化题库

选择题点选即时判分;填空题输入后"检查"或"显示答案"。

已答 0/0答对 0正确率
已答 0/0答对 0