白盒测试之路径覆盖与基本路径覆盖(蓝桥课学习笔记)
1、路径覆盖
实验介绍
程序中的路径是执行程序时经过的分支的集合。路径覆盖法是指设计一定数量的测试用例运行被测程序,使程序中的所有路径都至少被执行一次。路径覆盖率的计算方法为:测试时至少被执行过一次的路径总数 / 程序的总路径数。本实验主要通过实例介绍使用路径覆盖法设计白盒测试用例。
知识点
- 路径覆盖法设计白盒测试用例
实验内容
为了方便作比较,本实验仍然使用下列代码作为测试对象:
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 步:编写测试用例。
根据路径覆盖的定义,我们需要设计一些测试用例,使程序中的每个路径至少被执行一次。因此,我们可以设计如下表中的四个测试用例来覆盖这四条路径。
测试用例编号 | 输入数据 | 预期结果 | 路径覆盖情况 |
---|---|---|---|
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 |
路径覆盖可以使程序中的每一条路径都经过测试,确保程序执行路径的正确性。但是,对于判断语句多且复杂、循环次数多的程序,需覆盖的路径数量可能非常庞大,无法在短时间内测试完,例如,下图是一段代码的流程图,图中含有多个判断语句、循环语句,如果要将所有路径都测试到,将花费大量的时间,所以,在实际的项目测试中基本不可能把所有路径都覆盖到。
实验总结
路径覆盖可以保证程序中的所有路径都被覆盖到,但对于包含多且复杂的判断语句、循环语句的程序来说,要覆盖每一条路径将会非常困难,需要花费极大的人力物力。
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.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% 覆盖。如果使用基本路径覆盖法后程序中仍有未覆盖到的路径,可使用逻辑覆盖法补充测试用例保证覆盖全面。