Bootstrap

【软件测试】实验五 白盒测试实验

一、实验目的

  1. 巩固基于控制流白盒测试知识,对于给定的待测程序,能熟练应用基本控制流覆盖方法设计测试用例;
  2. 通过绘制程序控制流程图,实现对程序源代码的逻辑描述;
  3. 掌握逻辑短路对测试的影响;
  4. 培养严谨和系统的测试精神,学习测试用例的设计和分析。
  5. 掌握常用的静态测试工具

二、实验环境

  1. 硬件环境:PC 机一台
  2. 软件环境:Java 编程环境:Java SDK + Eclipse C/C++编程环境:Visual Studio
  3. 程序流程图绘制:Visio 环境、PPT下手工绘制 ;其它环境:ProcessOn 自动生成工具:Soot (http://sable.github.io/soot/),Visustin v7 等
  4. 待测程序:Demo
  5. Java 实验环境配置:
  • 在制定服务器或网站下载 Java SDK Eclipse
  • 配置 Java 运行环境
  • 启动 Eclipse

有精力和兴趣的同学可尝试用 Soot 辅助生成流程图,soot 的下载和安装如下

  1. 命令行方式:soot-trunk.jar      (参考 https://github.com/Sable/soot/wiki/Tutorials)
  2. Eclipse 插件方式:soot.zip   (参考 https://github.com/Sable/soot/wiki/Eclipse-Plugin-Installation)

三、实验内容

3.1 实验1:逻辑覆盖测试技术实验

3.1.1 实验背景

假设Z=1,输入两个整数x,y,通过程序判断返回值ret。程序Demo如下

public static int getNmb(int x,int y)
{
     int z = 1;
     int ret =0;
     if (x<0){
        z=y-x;
     }
     else{
        z=y+x;
     }
     if(z<10 && y>0)
     {
        ret = z*y;
     }
     else
     {
        ret= z*x;
     }
     return ret;
}

运用基于逻辑覆盖的动态白盒测试方法,对上述程序进行测试。设计测试用例时,尽可能设计最少的测试用例数,同时保证每种覆盖方法的覆盖率尽可能达到 100%。

任务:

  1. 给出 Demo程序流程图,这是进行基于控制流动态白盒测试的基础。
  2. 分别以语句覆盖和判定覆盖方法设计测试用例,并写出每个测试用例的执行路径。
  3. 分别以条件覆盖、判定条件覆盖和条件组合覆盖方法设计测试用例,并写出每个测试用例的执行路径。
  4. 基于Junit实现上述5组测试用例。并写出测试用例的覆盖情况,尽量达到全覆盖。最后导出测试结果报告。
  5. 请根据上述程序画出控制流图,计算其环路复杂度,并设计测试用例,覆盖基本路径。

3.1.2 实验过程注意事项:

  1.  程序流程图只有 1 个入口,1 个出口;
  2. 根据使用的测试方法,把判定和条件在测试用例执行时的取值给出来;
  3. 没有执行的判定和条件没有取值;
  4. 条件组合测试时,对一个判定中的条件取值进行组合;
  5. 复杂的条件组合要优先进行约简,然后再设计测试用例;

四、实验要求

1、根据题目要求编写测试用例。一些测试用例书写示例:

要点:根据测试方法的特点,把需要明确给出的判定或条件取值,以及路径等必要信息给出来

五、实验思考

  1. 通过测试,是否发现程序中存在的缺陷?
  2. 程序中是否还存在采用动态白盒测试技术未能发现的缺陷?
  3. 在存在逻辑短路的情况下,请分析条件覆盖、判定条件覆盖、条件组合覆盖的联系和区别。
  4. 在白盒测试实践中,你觉得哪些步骤是关键的?并谈谈你所体会到的白盒测试过程中的难点。

实验报告

一、逻辑覆盖测试技术实验

1.1 实验背景

假设Z=1,输入两个整数x,y,通过程序判断返回值ret。程序Demo见Demo.java文件。

1.2 实验过程

1.2.1 Demo程序流程图

1.2.2 语句覆盖和判定覆盖方法设计测试用例

如流程图所示,为每一条语句进行编号,如下表所示。

语句编号

语句

1

z = 1,ret = 0

2

x < 0 ?

3

z = y - x

4

z = x + y

5

z < 10 ?

6

y > 0 ?

7

ret = z * y

8

ret = z * x

9

return ret

(1)语句覆盖

语句覆盖要求测试用例覆盖程序中的每一个语句至少一次,即测试用例必须执行程序的每一行。有上述可知,本程序语句有abcdefghij,因此设计样例如下。

用例编号

输入

输出

执行路径

1

x = -1,y = 1

ret = 2

1->2->3->5->6->7->9

2

x = 1,y = -1

ret = 0

1->2->4->5->6->8->9

(2)判定覆盖

判定覆盖要求测试用例覆盖到程序中的每个判断的两个结果,即 if 语句的各个分支。由上述可知判断语句有 c、(fg),其中 d、e 为 c 的判断分支,h、i 为 fg 的判断分支。因此至少覆盖 dehi。故设计样例如下:

用例编号

输入

输出

执行路径

1

x = -1,y = -1

ret = 0

1->2->3->5->6->8->9

2

x = 1,y = 1

ret = 2

1->2->4->5->6->7->9

1.2.3 条件覆盖、判定条件覆盖和条件组合覆盖方法设计测试用例

(1)条件覆盖

条件覆盖要求测试用例覆盖程序中的每一个条件语句的两种结果至少一次。有上述可知,本程序语句的判断语句有cfg,因此设计样例如下。

用例编号

输入

输出

执行路径

条件判断

1

x = -2,y = -2

ret = 0

1->2->3->5->6->8->9

256=>TTF

2

x = 6,y = 6

ret = 2

1->2->4->5->6->7->9

256=>FFT

(2)判定条件覆盖

判定条件覆盖要求测试用例覆盖到程序中的每个判断的两个结果和每个条件语句的两种结果,即既满足判定覆盖又满足条件覆盖。故设计样例如下:

用例编号

输入

输出

执行路径

条件判断

1

x =10,y = 0

ret = 0

1->2->4->5->6->8->9

256=>FFF

2

x = -3,y = 1

ret = 4

1->2->3->5->6->7->9

256=>TTT

(3)条件组合覆盖

条件组合覆盖要求测试用例覆盖到程序中每个判断中的条件语句的结果组合。由上述可知,判断语句有c、(fg)。则需要使得c = {T,F},(fg)={TT,TF,FT,FF}均覆盖。故设计样例如下:

用例编号

输入

输出

执行路径

条件判断

1

x = -5,y = 5

ret = -50

1->2->3->5->6->7->9

256=>TTT

2

x = -5,y = -5

ret = 0

1->2->3->5->6->8->9

256=>TTF

3

x =5,y = 5

ret = 50

1->2->4->5->6->8>9

256=>FFT

4

x = 15,y = -5

ret = 150

1->2->4->5->6->8->9

256=>FFF

1.2.4 覆盖率测试

使用Idea自带的覆盖率工具运行得到结果如下。如图所示,测试样例通过率100%,行覆盖率100%。测试代码见demoTest.java文件。

二、实验结果

  1. 白盒测试的优点:代码覆盖率高,对代码的测试比较彻底,迫使测试人员仔细思考软件的实现,揭示隐藏在代码中的错误。缺点:测试开销大,无法检测代码中遗漏的路径和数据敏感性错误,不验证规格的正确性,覆盖所有代码路径难度大,业务功能可能覆盖不全。
  2. 本实验中,理论与实践的结合,更加深入体会到白盒测试的原理,对于给定的待测程序,能熟练应用基本控制流覆盖方法设计测试用例。通过绘制程序控制流程图,实现对程序源代码的逻辑描述,掌握逻辑短路对测试的影响。

实验代码

Demo.java

package course5;

public class Demo{
    public static int getResult(int x,int y){
        int z = 1, ret = 0;
        if (x < 0){
            z = y - x;
        }else {
            z = y + x;
        }
        if(z<10 && y>0){
            ret = z*y;
        }else {
            ret = z*x;
        }
        return ret;
    }
}

DemoTest.java

package course5;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvFileSource;

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class DemoTest {
    @ParameterizedTest
    @CsvFileSource(resources = {"/DemoDataSet.csv"})
    public void test(int a,int b,int expected){
        Assertions.assertEquals(expected,Demo.getResult(a,b));
    }
}

DemoDataSet.csv

-112
1-10
-1-10
112
-2-20
6672
100100
-314
-55-50
-5-50
5550
15-5150
;