常见的测试用例
常用的黑盒测试方法
等价类划分
边界值分析法
判定表法
案例一
简化表
案例二
因果图
案例


正交分解法
正交表查询的网址:
- 为方便读者使用,本书在附录 1 中列出了一些常用的正交表格。可通过附录查询适合的正交表。
- 通过链接查询:http://support.sas.com/techsup/technote/ts723_Designs.txt
正交法的正交性
案例 一
案例二
本来为2 的5次方,但是所提供的正交表没有2的5次方表,选择最近能覆盖的正交表2的7次方的表。
场景法
案例一
案例二
大纲法
错误推测法
测试用例逐级生成的策略
测试用例的粒度
软件缺陷报告


缺陷的基本信息
缺陷标题、操作步骤、预期结果、实际结果、备注/注释
缺陷的属性
缺陷的状态
缺陷的类型
缺陷报告的案例
回归测试

案例一
功能测试题目 3
利用所学知识,请对蓝桥后台管理中的如下 3 个页面进行测试,寻找其中预埋的 19 个缺陷,包括但不限于功能缺陷和易用性界面缺陷。 并把发现的缺陷填写在指定的【模拟赛1期缺陷报告.xlsx】缺陷报告模板中。
【功能1:登录功能】
还差一列7缺陷等级
缺陷编号 | 功能名称 | 缺陷描述 | 操作步骤 | 预期结果 | 实际结果 | 缺陷级别 |
DL-BUG-001 | 登录 | 登录页面,未勾选【记住我】,关闭浏览器再次打开仍然是登录状态。 | 1. 打开被测系统登录页; 2. 输入正确的用户信息,不勾选【记住我】,点击【登录】; 3. 登录成功后复制URL,并关闭浏览器(火狐); 4. 重新打开火狐浏览器,把URL粘贴到地址栏 | 在登录界面需要再次点击【登录】才能登录成功。 | 无需再次点击【登录】,直接打开登录成功后的页面。 | 1 |
DL-BUG-002 | 登录 | 登录页面,输入错误的验证码也可以成功登录。 | 1. 打开被测系统登录页; 2. 输入正确的用户名和密码; 3. 输入错误的验证码(和图片显示不一致); 4. 点击【登录】。 | 登录失败,提示【验证码错误】。 | 登录成功。 | 1 |
DL-BUG-003 | 登录 | 登录页面,密码输入框和用户名输入框没有对齐,界面不美观。 | 1. 打开被测系统登录页; 2. 查看页面布局。 | 界面美观,输入框对齐整洁。 | 用户名输入框和密码输入框没有对齐,不美观。 | 2 |
DL-BUG-004 | 登录 | 登录失败时,提示信息不正确。 | 1. 打开被测系统登录页; 2. 输入错误的用户名或密码; 3. 点击【登录】。 | 提示【用户名或密码错误】。 | 提示【注册失败】 | 2 |
YHGL-BUG-001 | 添加用户 | 添加用户页面,用户名重复也可以成功添加。 | 1. 登录成功后-->用户管理-->添加用户; 2. 在添加用户页面中输入已存在的用户名; 3. 在添加用户页面中其他项输入合法; 4. 点击【提交】。 | 提示【用户名已存在】。 | 没有提示,成功添加重复的用户名,与需求不符。 | 1 |
YHGL-BUG-002 | 添加用户 | 添加用户页面,登录名输入 2 个字符也可以成功添加。 | 1. 登录成功后-->用户管理-->添加用户; 2. 在添加用户页面中输入错误的登录名(少于3个字符); 3. 在添加用户页面中其他项输入合法; 4. 点击【提交】。 | 添加失败,提示:请输入3~12位之间的英文或数字。 | 添加成功。 | 1 |
YHGL-BUG-003 | 添加用户 | 添加用户页面,登录名输入多于12个字符也可以成功添加。 | 1. 登录成功后-->用户管理-->添加用户; 2. 在添加用户页面中输入错误的登录名(多于12个字符); 3. 在添加用户页面中其他项输入合法; 4. 点击【提交】。 | 添加失败,提示:请输入3~12位之间的英文或数字。 | 添加成功。 | 1 |
YHGL-BUG-004 | 添加用户 | 添加用户页面,登录名输入中文也可添加成功。 | 1. 登录成功后-->用户管理-->添加用户; 2. 在添加用户页面中输入错误的登录名(输入中文); 3. 在添加用户页面中其他项输入合法; 4. 点击【提交】。 | 添加失败,提示:请输入3~12位之间的英文或数字。 | 添加成功 | 1 |
YHGL-BUG-005 | 添加用户 | 添加用户页面,登录名区分大小写,不符合需求。 | 1. 登录成功后-->用户管理-->添加用户; 2. 在添加用户页面中输入已存在的大小写不同的登录名; 3. 在添加用户页面中其他项输入合法; 4. 点击【提交】。 | 添加失败,提示:登录名已存在。 | 添加成功。 | 1 |
YHGL-BUG-006 | 添加用户 | 添加用户页面,角色无法支持多选。 | 1. 登录成功后-->用户管理-->添加用户; 2. 在添加用户页面中选择角色; 3. 在添加用户页面中其他项输入合法; 4. 点击【提交】。 | 角色可多选。 | 角色只能单选。 | 1 |
YHGL-BUG-007 | 添加用户 | 添加用户页面,输入信息之后,点击【关闭】,没有给出提示信息。 | 1. 登录成功后-->用户管理-->添加用户; 2. 在添加用户页面中所有项输入合法的值; 3. 点击【关闭】按钮。 | 提示:确认要关闭页面吗? | 没有提示,直接关闭。 | 2 |
YHGL-BUG-001 | 用户管理 | 用户管理页面,导入功能不起作用。 | 1. 登录成功后-->打开用户管理页面; 2. 点击【导入】。 | 弹出导入窗口,选择文件可成功导入。 | 点击后没有反应。 | 1 |
YHGL-BUG-002 | 用户管理 | 用户管理页面,按用户状态搜索,不起作用。 | 1. 登录成功后-->打开用户管理页面; 2. 在上方搜索区域中,按用户状态进行搜索,选择不同的用户状态; 3. 点击【搜索】。 | 按用户的不同状态显示正确的查询结果。 | 选择不同的状态,查询结果没有变化。 | 1 |
YHGL-BUG-003 | 用户管理 | 用户管理页面,点击【导出】按钮,提示信息不正确。 | 1. 登录成功后-->打开用户管理页面; 2. 点击【导出】。 | 提示:导出全部用户信息。 | 提示:导出全部商品信息。 | 2 |
YHGL-BUG-004 | 用户管理 | 用户管理页面,点击【测试部门】显示用户列表,再点击【蓝桥科技】,用户信息显示不全,需刷新才行。 | 1. 登录成功后-->打开用户管理页面; 2. 点击【测试部门】查看测试部门的用户列表; 3. 再点击【蓝桥科技】,查看用户列表的显示。 | 点击【蓝桥科技】应显示全部用户列表。 | 点击【蓝桥科技】显示的用户列表不全,需刷新才可见。 | 2 |
YHGL-BUG-005 | 用户管理 | 用户管理页面,按时间进行搜索,结束时间可以早于开始时间。 | 1. 登录成功后-->打开用户管理页面; 2. 在上方搜索区域中,按时间进行搜索,选择【开始时间】和【结束时间】; 3. 点击【搜索】。 | 搜索时,结束时间不可以早于开始时间。 | 搜索时,结束时间可以早于开始时间。 | 2 |
YHGL-BUG-006 | 用户管理 | 用户管理页面,点击右侧的【删除】按钮没有弹出提示信息。 | 1. 登录成功后-->打开用户管理页面; 2. 点击用户列表后面的【删除】按钮; | 弹出提示信息:是否确定要删除? | 成功删除,没有提示信息。 | 2 |
YHGL-BUG-007 | 用户管理 | 用户管理页面,当用户信息为10条时,底部显示为第1到第11条记录。 | 1. 登录成功后-->打开用户管理页面; 2. 添加10个用户; 3. 查看底部显示信息。 | 显示:显示第1到第11条记录,总共10条记录。 | 显示:显示第1到第10条记录,总共10条记录。 | 2 |
YHGL-BUG-008 | 用户管理 | 用户管理页面,【更多操作】换行显示,界面不美观。 | 1. 登录成功后-->打开用户管理页面; 2. 添加至少1个用户; 3. 查看界面显示。 | 后面的操作按钮【更多操作】换行显示,界面不美观。 | 后面的操作按钮不会换行显示。 | 2 |
单元测试
语句覆盖
测试用例的覆盖率是指执行对应测试用例所覆盖到的测试覆盖项个数占全部测试覆盖项的百分比。白盒测试的覆盖标准有逻辑覆盖、循环语句覆盖和基本路径覆盖,其中逻辑覆盖主要包括语句覆盖、判定覆盖、条件覆盖、判定-条件覆盖、条件组合覆盖等。语句覆盖法是指设计适当数量的测试用例,使被测程序中的每条语句至少被执行一次。语句覆盖率的计算方法为:至少被执行一次的语句数量 / 程序中可执行的语句总数。
实验内容
public static int test(int a,int b,int c) {
1 int result = 0;
2 if(a == 0 or b > 2) {
3 result = b - a;
}
4 if(a > 0 and c > 0 ) {
5 result = c * a;
}
6 return result;
}
使用语句覆盖法设计白盒测试用例的具体步骤如下:
第 1 步:分析待测试程序,画出程序的流程图。上述代码的参考流程图如下图所示(为了方便后面的讲解,笔者在流程图中标上了序号)。如果对语句覆盖法比较熟悉或代码逻辑比较简单,也可以省略画流程图这一个步骤。
第 2 步:分析流程图,编写测试用例。
根据语句覆盖法的定义,我们需要设计一些测试用例,使程序中的每条语句至少被执行一次。通过对第一步中的流程图进行分析,我们设计如下表中的一个测试用例即可以将所有语句全部覆盖
测试用例编号 | 输入数据 | 预期结果 | 语句覆盖情况 |
---|---|---|---|
testcase_01 | a = 1 , b = 3 , c = 9 | result = 9 | 覆盖语句 1,2,4,3,5, 6 |
和黑盒测试的步骤类似,白盒测试用例设计完成,待开发人员提交测试版本后,即可以开始执行测试用例。白盒测试用例的执行一般使用专门的单元测试框架来执行,例如,执行本实验中的用例可以使用 java 的单元测试框架 JUnit 。本实验的重点是介绍白盒测试用例的设计方法,测试用例的执行方法将在单元测试课程中详细介绍。
语句覆盖的优点是可以使程序中的所有语句都得到验证。但是,只测试程序中的所有语句是远远不够的,程序中的执行逻辑并没有得到验证,不能找出程序逻辑方面的缺陷。在本例中,我们通过观察流程图可以发现:尽管设计一个测试用例就可以使所有语句都被覆盖到,但是图中的两个判断语句为“ N ”的分支可能完全没有验证到,因为这两个“ N ”分支上没有其他语句,所以测试用例并没覆盖到这个分支。
分支覆盖
分支覆盖,也叫判定覆盖,是指运行代码进行测试时,程序中的所有判定语句的真、假分支至少都被执行过一次。分支覆盖率的计算方法为:测试时覆盖到的判定语句真、假分支的总数 / 程序中判定语句真、假分支的总数。例如,判定语句 if a > 0 有真、假两个分支,如果设计一个测试用例 a = 3 ,则该判定语句的真分支可以被覆盖,分支覆盖率为 1 / 2 = 50% ; 如果设计两个测试用例 a = 3 ,a = -1 ,分别使用这两个测试用例数据执行被测试程序,则该判定语句的真、假分支都可以被覆盖到,分支覆盖率为 2 / 2 = 100% 。
白盒测试中的分支(判定)覆盖法是指设计适当数量的测试用例,运行被测程序,使得程序中每个判定语句的真、假分支至少被执行一次。流程图中一个菱形框就是一个判定语句,分支(判定)覆盖就是要设置一些测试用例使判定语句为 Y 和 N 的分支都至少被执行一次。本实验主要通过实例介绍使用分支(判定)覆盖法设计白盒测试用例的方法。
实验内容
public static int test(int a,int b,int c) {
1 int result = 0;
2 if(a == 0 or b > 2) {
3 result = b - a;
}
4 if(a > 0 and c > 0 ) {
5 result = c * a;
}
6 return result;
}
使用语句覆盖法设计白盒测试用例的具体步骤如下:
第 1 步:分析待测试代码,画出程序的流程图。上述代码的参考流程图如下图所示:
第 2 步:分析流程图,编写测试用例。
根据分支(判定)覆盖的定义,我们需要设计一些测试用例,使程序中的每个判定条件至少被执行一次,即上图中的判断语句 ② 和 ③ 的真、假分支都需要至少被执行一次。因此,我们可以设计如下表中的两个测试用例覆盖所有的真、假分支。
测试用例编号 | 输入数据 | 预期结果 | 分支覆盖情况 | 语句覆盖情况 |
---|---|---|---|---|
testcase_01 | a = 0 , b = 5 , c = 9 | result = 5 | 覆盖判断语句 ② 的真分支和判断语句 ③ 的假分支 | 1,2,4,3,6 |
testcase_02 | a = 5 , b = -2 , c = 3 | result = 15 | 覆盖判断语句 ② 的假分支和判断语句 ③ 的真分支 | 1,2,3,5,6 |
从上表中我们可以看出:如果程序的分支覆盖率达到 100% ,所有的语句也会被覆盖到,即分支覆盖率达到 100% 时,语句覆盖率也为 100% 。因为每个语句都是位于某个分支上的(入口主分支或判断语句分支)。但是,如果程序判定语句的逻辑存在问题,分支(判定)覆盖可能无法发现 。例如,在上述代码中,如果将判断语句 ② if(a = 0 or b > 2) 中的 or 错写成 and ,使用上面这两个用例仍然执行通过,也可以让分支(判定)覆盖率达到 100% ,但是这个逻辑错误却不能被发现。
实验总结
分支(判定)覆盖比语句覆盖的的覆盖效果要强一些,但是分支(判定)覆盖可能还是无法发现程序中的一些逻辑错误,仍需结合其他白盒测试用例设计方法才能覆盖全面。
条件覆盖
条件覆盖是指运行代码进行测试时,程序中所有判断语句中的条件取值为真值为假的情况都被覆盖到,即每个判断语句的所有条件取真值和假值的情况都至少被经历过一次。条件覆盖率的计算方法为:测试时覆盖到的条件语句真、假情况的总数 / 程序中条件语句真、假情况的总数。例如,判断语句 if(a == 0 or b > 2) 中有两个条件 a == 0 和 b > 2 ,使用条件覆盖法需要分别设计测试用例让这两个条件为真和为假的情况都被覆盖到。例如,设计测试用例 a = 0 ,b = 3 ,可以覆盖 a == 0 和 b > 2 这两个条件为真时的情况,此时程序的条件覆盖率为 2 / 4 = 50% ; 如果再设计一个测试用例 a = 1,b = 1 ,则可以将 a == 0 和 b > 2 这两个条件为假的情况也覆盖。也就是说,设计两个测试用例即可以让判断语句 if(a == 0 or b > 2) 的条件覆盖率达到 100% 。
实验内容
public static int test(int a,int b,int c) {
1 int result = 0;
2 if(a == 0 or b > 2) {
3 result = b - a;
}
4 if(a > 0 and c > 0 ) {
5 result = c * a;
}
6 return result;
}
使用条件覆盖法设计白盒测试用例的具体步骤如下:
第 1 步:分析待测试代码,画出程序的流程图。上述代码的参考流程图如下图所示:
第 2 步:分析流程图。
通过分析流程图,我们可以知道:这段代码中有两个判断语句,分别是上图中标识为 ② 和 ③ 的语句,语句 ② 中有两个条件,分别为 a == 0 和 b > 2 ;语句 ③ 中也有两个条件,分别为 a > 0 和 c > 0 。为了使后续的分析过程更加清晰明了,我们先来梳理一下流程图中的条件语句,并进行相应的标识,具体如下:
条件 | 取值 | 标识 |
---|---|---|
a == 0 | 真 | Y1 |
a == 0 | 假 | N1 |
b > 2 | 真 | Y2 |
b > 2 | 假 | N2 |
a > 0 | 真 | Y3 |
a > 0 | 假 | N3 |
c > 0 | 真 | Y4 |
c > 0 | 假 | N4 |
第 3 步:使用条件覆盖法编写测试用例
根据条件覆盖法的定义,我们需要设计一些测试用例,使程序中所有判定语句中的每个条件为真和为假的情况都至少被执行一次,即上表中列出的 8 种情况都需要至少被执行一次。因此,我们可以设计如下表中的测试用例来对程序中的四个条件进行覆盖:
测试用例编号 | 输入数据 | 预期结果 | 条件覆盖情况 | 分支覆盖情况 |
---|---|---|---|---|
testcase_01 | a = 0 , b = 5 , c = 9 | result = 5 | Y1、Y2、N3、Y4 | 判断语句 ② 的真分支和③ 的假分支 |
testcase_02 | a = 5 , b = 1 , c = -3 | result = 0 | N1、N2、Y3、N4 | 判断语句 ② 的假分支和 ③ 的假分支 |
通过对上表的分析我们可以发现 :条件覆盖可以使程序中判断语句的每个条件都至少被执行一次,但是,满足了条件覆盖也不能保证所有的分支都已经得到覆盖,例如,本例中的两个测试用例使程序达到了 100% 的条件覆盖,但分支(判定)覆盖只达到了 75%,判断语句 ③ 的真分支未能覆盖到,依然存在着漏测的风险。
实验总结
条件覆盖法可以使程序中判断语句的每个条件都至少被覆盖一次,但满足了条件覆盖却不一定会满足分支(判定)覆盖,对于有些程序判定的错误仍无法发现。
分支-条件覆盖
分支-条件覆盖,也叫判定-条件覆盖,是指运行代码进行测试时,程序中所有判断语句中的条件取值为真、取值为假的情况和整个判断语句取真分支、假分支的情况都被覆盖到(即,至少被执行过一次)。分支条件覆盖率的计算方法为:( 测试时覆盖到的条件语句为真、为假情况的总数 + 判断语句为真、为假情况的总数) / (程序中条件语句真、假情况的总数 + 判断语句为真、为假情况的总数)。例如,判断语句 if(a == 0 or b > 2) 中有两个条件 a == 0 和 b > 2 ,如果设计一个测试用例 a = 0 , b = 3 ,可以覆盖条件 a == 0 的真分支和条件 b > 2 的真分支,并可覆盖整个判断语句 if(a == 0 or b > 2) 的真分支,分支-条件覆盖率为 3 / 6 = 50%; 如果再设计一个测试用例 a = 2 , b = 2 ,则可以覆盖条件 a == 0 的假分支和条件 b > 2 的假分支,并可覆盖整个判断语句 if(a == 0 or b > 2) 的假分支,分支-条件覆盖率则可达到 100% 。
本实验主要通过实例介绍使用分支-条件覆盖法设计白盒测试用例的方法。
实验内容
public static int test(int a,int b,int c) {
1 int result = 0;
2 if(a == 0 or b > 2) {
3 result = b - a;
}
4 if(a > 0 and c > 0 ) {
5 result = c * a;
}
6 return result;
}
使用条件覆盖法设计白盒测试用例的具体步骤如下:
第 1 步:分析待测试代码,画出程序的流程图。上述代码的参考流程图如下图所示:
第 2 步:分析流程图。
通过分析流程图,我们可以知道:这段代码中有两个判断语句,分别是上图中标识为 ② 和 ③ 的语句,语句 ② 中有两个条件语句,分别为 a == 0 和 b > 2 ;语句 ③ 中也有两个条件,分别为 a > 0 和 c > 0 。为了使后续的分析过程更加清晰明了,我们先来梳理一下流程图中的判断语句及语句中的条件项,并进行相应的标识。
判断语句:
判断语句 | 取值 | 标识 |
---|---|---|
a == 0 or b > 2 | 真 | T1 |
a == 0 or b > 2 | 假 | F1 |
a > 0 and c > 0 | 真 | T2 |
a > 0 and c > 0 | 假 | F2 |
条件:
条件 | 取值 | 标识 |
---|---|---|
a == 0 | 真 | Y1 |
a == 0 | 假 | N1 |
b > 2 | 真 | Y2 |
b > 2 | 假 | N2 |
a > 0 | 真 | Y3 |
a > 0 | 假 | N3 |
c > 0 | 真 | Y4 |
c > 0 | 假 | N4 |
第 3 步:使用分支-条件覆盖法编写测试用例。
根据分支-条件覆盖法的定义,这种方法是将分支覆盖和条件覆盖结合起来,设计一些测试用例,使程序中每个判定语句中的每个条件为真和为假的情况都至少被执行一次,并且每个判断语句本身为真、为假的情况也至少被执行一次。因此,我们可以设计如下表中的测试用例来对程序中的两个判断语句及其四个条件进行覆盖:
测试用例编号 | 输入数据 | 预期结果 | 条件覆盖情况 | 分支覆盖情况 |
---|---|---|---|---|
testcase_01 | a = 0 , b = 5 , c = 0 | result = 5 | Y1、Y2、N3、N4 | T1、F2 |
testcase_02 | a = 5 , b = 1 , c = 3 | result = 15 | N1、N2、Y3、Y4 | F1、T2 |
通过执行以上两个用例可以实现程序的分支-条件 100% 覆盖。那么,是不是实现了分支-条件覆盖就代表程序已经被覆盖全面了呢?下图是该程序标识了执行路径的流程图:
从上图中可以看出,这段代码共有四条路径,分别为:路径 1( A - C )、路径 2( A - D )、路径 3 ( B - C )、路径 4( B - D )。通过分析,我们可以知道:测试用例 testcase_01 覆盖的路径是路径 3 ( B - C ),测试用例 testcase_02 覆盖的路径是路径 2( A - D ),路径 1 和路径 4 没有被覆盖到。所以,分支-条件覆盖的覆盖强度仍然不够,如果判断语句中的逻辑运算存在问题可能仍然无法被发现。例如,如果将第一个判断语句 if(a == 0 or b > 2) 中的 or 错写成了 and ,使用这两个测试用例仍然能执行通过,但未检查出程序中的逻辑运算错误。
实验总结
分支-条件覆盖可以使程序中的判断语句以及判断语句中的条件的真、假分支都得到覆盖,但是分支-条件覆盖达到 100% 仍然强度不够,程序中的某些逻辑运算等错误仍然可能不会被发现。
条件组合覆盖
条件组合覆盖又称为多条件覆盖,是指设计足够数据的测试用例,使每个判定语句中的所有判定条件的各种可能的组合都至少被执行一次。条件组合覆盖与分支-条件覆盖的不同之处在于:条件组合覆盖不是简单的要求每个条件为真、为假两种情况都至少被执行一次,而是要求让每个条件为真、为假情况所有可能的组合都至少被执行一次。例如,判断语句 if ( a == 0 or b > 2 ) 中有两个条件 a == 0 和 b > 2 ,使用条件组合覆盖法设计测试用例时,要求这两个条件的取真值和取假值的组合至少各执行一次,即 a == 0(真)与 b > 2 (真)、a == 0(真)与 b > 2 (假)、 a == 0(假)与 b > 2 (真)、 a == 0(假)与 b > 2 (假)这四种组合情况。
本实验主要通过实例介绍使用条件组合覆盖法设计白盒测试用例。
实验内容
public static int test(int a,int b,int c) {
1 int result = 0;
2 if(a == 0 or b > 2) {
3 result = b - a;
}
4 if(a > 0 and c > 0) {
5 result = c * a;
}
6 return result;
}
使用条件组合覆盖法设计白盒测试用例的具体步骤如下:
第 1 步:分析待测试代码,画出程序的流程图。上述代码的参考流程图如下图所示:
标识了路径的流程图如下:
第 2 步:分析流程图。
由流程图可知:这段代码中有两个判断语句,分别是上图中标识为 ② 和 ③ 的语句,语句 ② 中有两个条件语句,分别为 a == 0 和 b > 2 ;语句 ③ 中也有两个条件,分别为 a > 0 和 c > 0 。为了使后续的分析过程更加清晰明了,我们先将条件语句进行相应的标识,具体如下:
条件 | 取值 | 标识 |
---|---|---|
a == 0 | 真 | Y1 |
a == 0 | 假 | N1 |
b > 2 | 真 | Y2 |
b > 2 | 假 | N2 |
a > 0 | 真 | Y3 |
a > 0 | 假 | N3 |
c > 0 | 真 | Y4 |
c > 0 | 假 | N4 |
根据条件组合覆盖法的定义,我们需要设计一些测试用例分别使判断语句 ② 中两个条件的四种组合及判断语句 ③ 中两个条件的四种组合都至少执行一次,如下表所示:
组合编号 | 判断语句 | 条件组合 |
---|---|---|
1 | a == 0 or b > 2 | Y1 + Y2 |
2 | a == 0 or b > 2 | Y1 + N2 |
3 | a == 0 or b > 2 | N1 + Y2 |
4 | a == 0 or b > 2 | N1 + N2 |
5 | a > 0 and c > 0 | Y3 + Y4 |
6 | a > 0 and c > 0 | Y3 + N4 |
7 | a > 0 and c > 0 | N3 + Y4 |
8 | a > 0 and c > 0 | N3 + N4 |
第 3 步:使用条件组合覆盖法编写测试用例。
分别设计测试用例覆盖上表中的各种组合,具体如下:
测试用例编号 | 输入数据 | 预期结果 | 条件组合覆盖 | 条件覆盖 | 路径覆盖 |
---|---|---|---|---|---|
testcase_01 | a = 0 , b = 3 , c = 1 | result = 3 | 组合 1 、组合 7 | Y1、Y2、N3、Y4 | B - C |
testcase_02 | a = 0 , b = 1 , c = 0 | result = 1 | 组合 2 、组合 8 | Y1、N2、N3、N4 | B - C |
testcase_03 | a = 1 , b = 5 , c = 3 | result = 3 | 组合 3 、组合 5 | N1、Y2、Y3、Y4 | B - D |
testcase_04 | a = 2 , b = 0 , c = -1 | result = 1 | 组合 4 、组合 6 | N1、N2、Y3、N4 | A - C |
通过对上表的分析我们可以发现 :条件组合覆盖可以使程序判断断语句中的条件组合都至少被执行一次,但是,满足了条件组合覆盖也不能保证所有的路径都已经得到覆盖,在本例中,四个测试用例实现了条件组合的 100% 覆盖,但是仍有路径 A - D 未被覆盖到。如果要将路径全部覆盖,需要再增加一个覆盖路径 A - D 的测试用例,即使用条件组合 + 分支覆盖的全部测试用例如下:
测试用例编号 | 输入数据 | 预期结果 | 条件组合覆盖 | 条件覆盖 | 路径覆盖 |
---|---|---|---|---|---|
testcase_01 | a = 0 , b = 3 , c = 1 | result = 3 | 组合 1 、组合 7 | Y1、Y2、N3、Y4 | B - C |
testcase_02 | a = 0 , b = 1 , c = 0 | result = 1 | 组合 2 、组合 8 | Y1、N2、N3、N4 | B - C |
testcase_03 | a = 1 , b = 5 , c = 3 | result = 3 | 组合 3 、组合 5 | N1、Y2、Y3、Y4 | B - D |
testcase_04 | a = 2 , b = 0 , c = -1 | result = 0 | 组合 4 、组合 6 | N1、N2、Y3、N4 | A - C |
testcase_05 | a = 2 , b = 0 , c = 5 | result = 10 | 组合 4 、组合 5 | N1、N2、Y3、Y4 | A - D |
路径覆盖
路径覆盖法是指设计一定数量的测试用例运行被测程序,使程序中的所有路径都至少被执行一次。路径覆盖率的计算方法为:测试时至少被执行过一次的路径总数 / 程序的总路径数。本实验主要通过实例介绍使用路径覆盖法设计白盒测试用例。
实验内容
public static int test(int a,int b,int c) {
1 int result = 0;
2 if(a == 0 or b > 2) {
3 result = b - a;
}
4 if(a > 0 and c > 0 ) {
5 result = c * a;
}
6 return result;
}
使用路径覆盖法设计白盒测试用例的具体步骤如下:
第 1 步:分析待测试代码,画出程序的流程图。上述代码的参考流程图如下图所示,为了方便分析路径,图中用红色字母标识出了每个判断语句的分支:
第 2 步:分析流程图。
从上图中可以看出,这段代码共有两个判断语句,每个判断语句分别有取真值、取假值两个分支。那么,程序中共有如下四条路径:
路径 1 :A - C 路径 2 :A - D 路径 3 :B - C 路径 4 :B - D
第 3 步:编写测试用例。
根据路径覆盖的定义,我们需要设计一些测试用例,使程序中的每个路径至少被执行一次。因此,我们可以设计如下表中的四个测试用例来覆盖这四条路径。
第 3 步:编写测试用例。
根据路径覆盖的定义,我们需要设计一些测试用例,使程序中的每个路径至少被执行一次。因此,我们可以设计如下表中的四个测试用例来覆盖这四条路径。
测试用例编号 | 输入数据 | 预期结果 | 路径覆盖情况 |
---|---|---|---|
testcase_01 | a = -2 , b = 1 , c = 9 | result = 0 | 路径 1 :A - C |
testcase_02 | a = 5 , b = -2 , c = 3 | result = 15 | 路径 2 :A - D |
testcase_03 | a = 0 , b = 3 , c = 3 | result = 3 | 路径 3 :B - C |
testcase_04 | a = 1 , b = 5 , c = 9 | result = 9 | 路径 4 :B - D |
路径覆盖可以使程序中的每一条路径都经过测试,确保程序执行路径的正确性。但是,对于判断语句多且复杂、循环次数多的程序,需覆盖的路径数量可能非常庞大,无法在短时间内测试完,例如,下图是一段代码的流程图,图中含有多个判断语句、循环语句,如果要将所有路径都测试到,将花费大量的时间,所以,在实际的项目测试中基本不可能把所有路径都覆盖到。
实验总结
路径覆盖可以保证程序中的所有路径都被覆盖到,但对于包含多且复杂的判断语句、循环语句的程序来说,要覆盖每一条路径将会非常困难,需要花费极大的人力物力。
基本路径覆盖
基本路径覆盖法是在程序控制流图的基础上,通过分析控制结构的圈复杂度,导出基本可执行的路径集合设计测试用例,运行被测程序,使程序的基本路径都得到覆盖。基本路径覆盖法把测试时需要覆盖的路径压缩到一定的范围内,使程序中的每一个可执行语句都至少执行一次,程序中的循环体最多只执行一次。本实验主要通过实例介绍使用基本路径覆盖法设计白盒测试用例
实验内容
public static int test(int a,int b,int c) {
1 int result = 0;
2 if(a == 0 or b > 2) {
3 result = b - a;
}
4 if(a > 0 and c > 0 ) {
5 result = c * a;
}
6 return result;
}
使用基本路径覆盖法设计白盒测试用例的具体步骤如下:
第 1 步:分析待测试代码,画出程序的流程图。参考流程图如下图所示,如果对该方法比较熟练或对程序流程比较清晰,可省略这个步骤。
在第二章的“ 2.2.2 控制流分析”小节中曾介绍过“在控制流图中如果含有复合条件,需要改为单条件嵌套的形式”,为了后续的讲述更加清晰,这里先把上述流程图中的复合条件按控制流图的要求进行拆分,具体如下:
第 2 步:根据流程图画出控制流图。
控制流图的画法在第二章的“ 2.2.2 控制流分析”小节中已详细介绍,此处不再详细介绍,只进行简单的回顾。在控制流图中,圆形符号○称为“节点”,表示一个基本的代码块;包含条件的节点称为“判断节点”;箭头称为“边”,表示控制流路径,反向边则表示可能存在循环。按照控制流图的规则,上述流程图可以画成下面的控制流图:
第 2 步:根据流程图画出控制流图。
控制流图的画法在第二章的“ 2.2.2 控制流分析”小节中已详细介绍,此处不再详细介绍,只进行简单的回顾。在控制流图中,圆形符号○称为“节点”,表示一个基本的代码块;包含条件的节点称为“判断节点”;箭头称为“边”,表示控制流路径,反向边则表示可能存在循环。按照控制流图的规则,上述流程图可以画成下面的控制流图:
第 3 步:计算圈复杂度。
圈复杂度 V(G) 有三种计算方法,在第二章的“复杂度分析”小节已详细介绍过,读者可以任选其中一种方法来进行计算。下面简单介绍一下用这三种方法计算本例的圈复杂度:
方法一:V(G) = A + 1,其中 A 代表控制流图中的封闭区域数量。从下图可以看出,程序的控制流图中共有 4 个封闭区域,所以,圈复杂度 V(G) = 4 + 1 = 5 。
方法二:V(G) = P + 1,其中 P 代表控制流图中的判定节点数。从下图可以看出,程序的控制流图中共有 4 个判定节点,所以,圈复杂度 V(G) = 4 + 1 = 5 。
方法三:V(G) = e - n + 2,其中 e 代表控制流图中的边的数量,即控制流中的箭头数量;n 代表控制流图的节点数量,即控制流图中的圆圈数量。从下图中可以看出,程序的控制流图中有 11 条边(11个箭头),8个节点(8个圆圈),所以,圈复杂度 V(G) = 11 - 8 + 2 = 5 。
第 4 步:确定基本路径的集合。
基本路径又称为独立路径,是指至少包含一条其他独立路径中未包含的路径。例如,在上图中,路径 1 - 2 - 3 - 5 - 8 是一条基本路径,1 - 2 - 4 - 3 - 5 - 8 则可以看成了另外一条基本路径,因为这条路径中经过 4 节点的路径在第一条基本路径中未包含。
圈复杂度是指程序中的独立路径数量,是确保程序中每个可执行语句至少执行一次需要的测试用例数量的最小值。根据第 3 步的计算结果,本例中我们需要确定 5 条基本路径,具体如下:
路径 1 :1 - 2 - 3 - 5 - 8
路径 2 :1 - 2 - 4 - 3 - 5 - 8
路径 3 :1 - 2 - 4 - 5 - 8
路径 4 :1 - 2 - 4 - 5 - 6 - 8
路径 5 :1 - 2 - 4 - 5 - 6 - 7 - 8
第 5 步:根据基本路径编写测试用例。
根据基本路径覆盖法的定义,我们需要设计测试用例分别覆盖第 4 步中的 5 条基本路径,即设计合理的输入数据使程序运行时经过指定的路径。因此,我们可以设计如下表中的 5 个测试用例来覆盖这 5 条基本路径。
测试用例编号 | 输入数据 | 预期结果 | 路径基本覆盖情况 |
---|---|---|---|
testcase_01 | a = 0 , b = 1 , c = 9 | result = 1 | 路径 1 |
testcase_02 | a = 0 , b = 3 , c = 5 | result = 3 | 路径 2 |
testcase_03 | a = -2 , b = 1 , c = 3 | result = 0 | 路径 3 |
testcase_04 | a = 1 , b = 0 , c = -1 | result = 0 | 路径 4 |
testcase_05 | a = 5 , b = -3 , c = 2 | result = 10 | 路径 5 |
实验总结
使用基本路径覆盖法设计用例进行测试时,可以使程序中的每条独立路径都至少执行一次。如果程序中的基本路径达到了 100% 覆盖,则分支(判定)覆盖、条件覆盖也能达到 100% 覆盖。如果使用基本路径覆盖法后程序中仍有未覆盖到的路径,可使用逻辑覆盖法补充测试用例保证覆盖全面。