0

    白盒测试中路径覆盖和基本路径覆盖的不同

    2023.05.23 | admin | 213次围观

    测试方法会不会关注程序内部的结构可以将其划分为白盒测试和黑盒测试以及灰盒测试,黑盒测试不关注程序内部的实现结构,仅仅是通过向程序进行输入来观察程序的输出对不对;白盒测试就需要关注程序内部的实现结构,对程序的代码逻辑结构实施相关的测试;下面来简单介绍一下路径覆盖法和基本路径覆盖法两种白盒测试方法。

    路径覆盖法

    路径覆盖法是通过测试代码中的每个可能路径来检查代码的每个部分是否按照预期工作。路径覆盖法要求测试用例覆盖每个可能的路径,包括所有可能的循环和分支情况。这种方法需要编写大量的测试用例来覆盖所有可能的路径,因此它往往比较费时和费力。

    接下来以一段代码作为测试对象:

    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 步:分析待测代码,画出程序的流程图。上述代码的参考流程图如下所示,为了方便分析路径,图中红色字母 A、B、C、D 标识出了每个判断语句的分支:

    流程图

    第 2 步:分析流程图

    从上图中可以看出,这段代码共有 2 个判断语句,每个判断语句分别有取真值、取假值两个分支。那么,程序中共有如下四条路径:

    第 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

    综上所述,路径覆盖可以使程序中的每一条路径都经过测试,确保程序执行路径的正确性。但是,对于判断语句多且复杂、循环次数多的程序,需覆盖的路径数量可能非常庞大,无法在短时间内测试完,例如,下图是一段代码的流程图,图中含有多个判断语句、循环语句,如果要将所有路径都测试到,将花费大量的时间,所以,在实际的项目测试中基本不可能把所有路径都覆盖到。

    复杂流程图

    基本路径覆盖法

    路径覆盖可以使程序中的路径都被测试到,但是,要对程序中的路径做到完全覆盖经常是无法实现的。为了解决这一难题,我们需要在保证测试质量的前提下把测试的路径数量压缩到一定的范围内,基础路径覆盖法正好可以解决该问题。

    基本路径覆盖法是在程序控制流图的基础上,通过分析控制结构的圈复杂度,导出基本可执行的路径集合设计测试用例,运行被测程序,使程序的基本路径都得到覆盖。基本路径覆盖法把测试时需要覆盖的路径压缩到一定的范围内,使程序中的每一个可执行语句都至少执行一次,程序中的循环体最多只执行一次。

    为了方便比较,仍以上述代码作为测试对象,使用基本路径覆盖法来设计白盒测试用例,基本步骤如下:

    第 1 步:分析待测试代码,画出程序的流程图(和路径覆盖法中流程图一样),如果对该方法比较熟练或对程序流程比较清晰,可省略这个步骤。

    我们知道,在控制流图中如果含有复合条件,需要改为单条件嵌套的形式。为了后续的讲述更加清晰,这里先把上述流程图中的复合条件按控制流图的要求进行拆分,具体如下:

    单条件嵌套流程图

    第 2 步:根据流程图画出控制流图。

    白盒测试中路径覆盖和基本路径覆盖的不同

    在控制流图中,圆形符号 ○ 称为“节点”,表示一个基本的代码块;包含条件的节点称为 “ 判断节点 ” ;箭头称为 “ 边 ”,表示控制流路径,反向边则表示可能存在循环。按照控制流图的规则,上述流程图可以画成下面的控制流图:

    程序的基本控制流图

    第 3 步:计算圈复杂度。

    圈复杂度 V(G) 有三种计算方法,下面简单介绍一下用 3 种方法计算本例的圈复杂度:

    方法一: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 条基本路径,具体如下:

    第 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% 覆盖。如果使用基本路径覆盖法后程序中仍有未覆盖到的路径,可使用逻辑覆盖法补充测试用例保证覆盖全面。

    在本案例中,基本路径法设计出的测试用例反而比路径法多一条,那是因为二者的覆盖方法不一样导致的,如果是在有组合关系或者循环逻辑的代码中,基本路径法就会简单很多。

    版权声明

    本文仅代表作者观点。
    本文系作者授权发表,未经许可,不得转载。

    发表评论