资源描述
第5章 动态测试技术(2)-白盒测试方法
教学内容:
1. 掌握白盒测试的基本概念
2. 掌握逻辑覆盖、基本路径覆盖白盒测试方法
3. 理解其他白盒测试方法(循环测试、数据流测试、变异测试、域测试、Z路径覆盖)的内容及其对逻辑覆盖测试的补充
4. 了解白盒测试方法的选择策略
课型:新授课
教时:8课时
教学重点:
1. 白盒测试基本概念
2. 逻辑覆盖测试
3. 基本路径测试
4. 开源白盒测试工具的使用方法
1. 白盒测试概述
1. 定义:根据程序内部的逻辑结构及相关信息设计测试用例
2. 主要的黑盒测试方法有
2.1 逻辑覆盖测试
2.2 基本路径覆盖测试
2.3 循环测试
2.4 程序插装
2.5 程序变异测试
2.6 其他白盒测试
Ø 数据流测试
Ø 域测试
Ø Z路径覆盖
Ø 符号测试
2. 逻辑覆盖测试
1. 概述:
1.1 考察使用测试数据运行被测程序时对程序逻辑的覆盖程度
1.2 希望选择最少的测试用例来满足所需的覆盖标准
1.3 常用的覆盖标准
Ø 语句覆盖
Ø 判定覆盖
Ø 条件覆盖
Ø 判定-条件覆盖
Ø 条件组合覆盖
Ø 路径覆盖
2. 实例
2.1 题目要求:
对下列子程序进行测试
procedure example(y,z:real;var x:real);
begin
if (y>1) and (z=0) then x:=x/y;
if (y=2) or (x>1) then x:=x+1;
end;
该子程序接受x、y、z的值,并将计算结果x的值返回给调用程序。
与该子程序对应的流程图如下:
该子程序有两个判定:
a: (y>1) and (z=0)
c: (y=2) or (x>1)
判定a中有两个条件: y>1、 z=0
判定c中有两个条件: y=2 、x>1
2.2 根据程序的执行流程可知:
l 当判定a为“假”时,判定C中的x就是输入的x值,此时,相对于输入的x而言,判定C中的“x>1”就是“x>1”
l 当判定a为“真”时,判定C中的x是经过x=x/y计算后的值,此时,相对于输入的x而言,判定C中的“x>1”实际是“x/y>1”,即“x>y”
2.3 该子程序有四条可执行路径:
Ø 路径1 sabcde , 其执行条件(L1)是a为“t”且c为“t”
L1= {(y>1) and (z=0)} and
{(y=2) or (x/y>1)}
= (y>1) and (z=0) and (y=2) or
(y>1) and (z=0) and (x> y )
= (y=2) and (z=0) or
(y>1) and (z=0) and (x> y )
Ø 路径2 sace ,其执行条件(L2)是
a为“f”且c为“f”
L2 = not{(y>1) and (z=0)} and
not{(y=2) or (x>1)}
= { not (y>1) or not (z=0) } and
{ not (y=2) and not (x>1) }
= not (y>1) and not (y=2) and not (x>1)
or
not (z=0) and not (y=2) and not (x>1)
=(y≤1) and (x ≤ 1)
or
(z ≠ 0) and (y ≠ 2) and (x ≤ 1)
Ø 路径3 sacde ,其执行条件(L3)是
a为“f”且c为“t”
L3 = not {(y>1) and (z=0)} and
{(y=2) or (x>1)}
= { not (y>1) or not (z=0)} and
{(y=2) or (x>1)}
= not (y>1) and (y=2) or
not (y>1) and (x>1) or
not (z=0) and (y=2) or
not (z=0) and (x>1)
= (y ≤ 1) and (x>1) or
(z ≠ 0) and (y=2) or (z ≠ 0) and (x>1)
Ø 路径4 sabce ,其执行条件(L4)是
a为“t”且c为“f”
L4 = {(y>1) and (z=0)} and
not {(y=2) or (x/y>1)}
= (y>1) and (z=0) and not (y=2) and not (x> y)
=(y>1) and (z=0) and (y ≠ 2) and (x ≤ y)
3. 语句覆盖:
3.1 语句覆盖是指选择足够的测试用例,使得运行这些测试用例时,被测程序的每个可执行语句都至少执行一次
3.2 执行条件L1(t,t)
(y=2) and (z=0) or
(y>1) and (z=0) and (x> y )
测试数据
预期结果
x=4,y=2,z=0
x=3
4. 判定覆盖
4.1 判定覆盖(也称分支覆盖)是指选择足够的测试用例,使得运行这些测试用例时,被测程序的每个判定的所有可能结果都至少执行一次(即判定的每个分支至少经过一次)
4.2 执行条件L3(f,t)和L4 (t,f)
或者执行条件L1(t,t)和L2(f,f)
l 选择执行条件L3(f,t)和L4 (t,f)
l L3 =(y ≤ 1) and (x>1) or (z ≠ 0) and (y=2) or (z ≠ 0) and (x>1)
l L4 =(y>1) and (z=0) and (y ≠ 2) and (x ≤ y)
测试数据
预期结果
路径
a
c
x=1,y=2,z=1
x=2
sacde
f
t
x=3,y=3,z=0
x=1
sabce
t
f
5. 条件覆盖
5.1 条件覆盖是指选择足够的测试用例,使得运行这些测试用例时,被测程序的每个判定中的每个条件的所有可能结果都至少出现一次
测试数据
预期结果
路径
覆盖的条件
x=1,y=2,z=0
x=1.5
sabcde
y>1, z=0, y=2,x ≤ y
x=2,y=1,z=1
x=3
sacde
y ≤ 1,z ≠ 0, y ≠ 2 ,x>1
6. 判定/条件覆盖
6.1 判定/条件覆盖是指选择足够的测试用例,使得运行这些测试用例时,被测程序的每个判定的所有可能结果都至少执行一次,并且,每个判定中的每个条件的所有可能结果都至少出现一次
6.2 执行条件L1(t,t)和L2(f,f)
测试数据
预期结果
路径
a
c
覆盖的条件
x=4,y=2,z=0
x=3
sabcde
t
t
y>1, z=0, y=2,x > y
x=1,y=1,z=1
x=1
sace
f
f
y ≤ 1,z ≠ 0,y ≠ 2 ,x ≤1
7. 条件组合覆盖
7.1 条件组合覆盖是指选择足够的测试用例,使得运行这些测试用例时,被测程序的每个判定中条件结果的所有可能组合都至少出现一次
7.2 判定a中条件结果的所有可能组合:
①y>1, z=0 ② y>1, z ≠ 0
③y ≤ 1 , z=0 ④ y ≤ 1 , z ≠ 0
7.3 判定c中条件结果的所有可能组合:
⑤ y=2, x>1 ⑥ y=2, x ≤ 1 ;
⑦ y ≠ 2 , x>1 ⑧ y ≠ 2 , x ≤ 1
测试数据
预期结果
路径
a
c
覆盖的条件
x=4,y=2,z=0
x=3
sabcde
t
t
①y>1,z=0
⑤y=2,x>y
x=1,y=2,z=1
x=2
sacde
f
t
②y>1,z ≠ 0
⑥y=2,x ≤ 1
x=2,y=1,z=0
x=3
sacde
f
t
③y ≤ 1,z=0
⑦y ≠ 2,x>1
x=1,y=1,z=1
x=1
sace
f
f
④y ≤ 1,z ≠ 0
⑧y ≠ 2,x≤1
8. 路径覆盖
8.1 路径覆盖是指选择足够的测试用例,使得运行这些测试用例时,被测程序的每条可能执行到的路径都至少经过一次(如果程序中包含环路,则要求每条环路至少经过一次)
测试数据
预期结果
路径
a
c
x=4,y=2,z=0
x=3
sabcde
t
t
x=3,y=3,z=0
x=1
sabce
t
f
x=2,y=1,z=0
x=3
sacde
f
t
x=1,y=1,z=1
x=1
sace
f
f
9. 逻辑覆盖测试需注意的问题
9.1 在逻辑覆盖测试时,我们强调“运行这些测试用例时”覆盖了被测程序的哪些判定、条件或路径
9.2 这表明在使用这些测试用例运行被测程序时,能执行到相应的判定、条件或路径
9.3 当运行测试数据y = 12时,其执行路径是sacg,覆盖了判定a为真的情况(即覆盖y >10)。由于其执行路径未经过判定b,所以这个测试数据并不覆盖判定b为真的情况(即不覆盖条件y > 5)
9.4 而运行测试数据y = 8时,其执行路径是sabdg,所以该测试数据覆盖了判定a为假的情况(即覆盖y £ 10)和判定b为真的情况(即覆盖y > 5)
10. 逻辑表达式错误敏感的测试
10.1 逻辑覆盖测试依赖于程序中的逻辑条件,这些逻辑条件由逻辑表达式组成
10.2 对于一个含有n个逻辑变量或关系表达式的逻辑表达式,通常需要2n个测试用例来覆盖其所有可能的条件组合
10.3 当n较大时,我们可以选择对发现逻辑表达式错误比较敏感的组合条件进行测试,以较少的测试用例来发现逻辑表达式中的绝大多数错误
10.4 Tai提出的分支与关系运算符(branch and relational operator,BRO)测试技术,能用较少的测试用例发现条件中分支与关系运算符的大多数错误
10.5 采用BRO方法的前提条件:条件中的每个布尔变量和关系运算符至多出现一次,并且无公共变量
10.6 BRO方法引入条件约束的概念,含有n个简单条件Ci的复合条件C的约束D表示为(D1,D2,…Dn), Di (0<i£n)表示在Ci的结果(outcome)上的约束,它一般是某种符号
10.7 对逻辑变量,约束为t或f (真、假);对关系表达式,约束为<、>、=
10.8 符合条件C的一次执行覆盖条件约束D是指,C中出现的每个简单条件Ci在这次执行中都满足D中对应的约束Di
10.9 下面分三种情况讨论:
Ø 若条件为C:B1&B2
其中B1、B2为逻辑变量,C的约束具有形式(D1,D2), D1和D2为t或f
则C可能的三种约束为{(t,t),(f,t),(t,f)}
对其中的每一组设计一个测试用例
而(f,f)对条件C是不敏感的
Ø 若条件为C:B1 or B2
其中B1、B2为逻辑变量
同理,C可能的三种约束为{(f,t),(t,f),(f,f)}
对其中的每一组设计一个测试用例
而(t,t)对条件C是不敏感的
Ø 若条件为C:B1&(E3=E4)
其中B1为逻辑变量, E3和E4为算术表达式
C的约束形式为(D1,D2)
D1为t或f
当E3=E4时D2为=
当E3¹E4时D2为< 或 >
则C可能的约束集合为{(t,=),(f,=),(t, < ), (t, > )}
而(f, < )和(f, > )对条件C是不敏感的
Ø 若条件为C: (E1 > E2) &(E3=E4)
其中E1、E2、E3、E4均为算术表达式
则C可能的约束集合为{( > ,=),
(=,=), ( < ,=) ,( > , < ), ( > , > )}
而其他约束对条件C是不敏感的
3. 基本路径覆盖测试
1. 概述:
1.1 在实际问题中,一个不太复杂的程序,特别是包含循环的程序,其路径数可能非常大
1.2 因此测试常常难以做到覆盖程序中的所有路径,为此,我们希望把测试的程序路径数压缩到一定的范围内
1.3 基本路径测试是Tom McCabe提出的一种白盒测试技术,这种方法首先根据程序或设计图画出控制流图,并计算其区域数,然后确定一组独立的程序执行路径(称为基本路径),最后为每一条基本路径设计一个测试用例
2. 程序的控制流图(也称程序图):
2.1 控制流图由结点和边组成,分别用圆和箭头表示
2.2 设计图中一个连续的处理框(对应于程序中的顺序语句)序列和一个判定框(对应于程序中的条件控制语句)映射成控制流图中的一个结点
2.3 设计图中的箭头(对应于程序中的控制转向)映射成流图中的一条边
2.4 对于设计图中多个箭头的交汇点可以映射成流图中的一个结点(空结点)
2.5 上述映射的前提是设计图的判定中不包含复合条件
2.6 如果设计图的判定中包含了复合条件,那么必须先将其转换成等价的简单条件设计图
2.7 我们把控制流图中由结点和边组成的闭合部分称为一个区域(region),在计算区域数时,图的外部部分也作为一个区域
2.8 例如,右图所示的流图的区域数为3
2.9 独立路径是指程序中至少引进一个新的处理语句序列或一个新条件的任一路径,在流图中,独立路径至少包含一条在定义该路径之前未曾用到过的边
2.10 在基本路径测试时,独立路径的数目就是流图的区域数
3. 实例:
例如,对一个PDL程序进行基本路径测试,该程序的功能是:最多输入N个值(以-999为输入结束标志),计算位于给定范围内的那些值(称为有效输入值)的平均值,以及输入值的个数和有效值的个数
其区域数为6
l 路径1:1-2-10-11-13
l 路径2:1-2-10-12-13
l 路径3:1-2-3-10-11-13
l 路径4:1-2-3-4-5-8-9-2-10-12-13
l 路径5:1-2-3-4-5-6-8-9-2-10-12-13
l 路径6:1-2-3-4-5-6-7-8-9-2-10-11-13
为每一条独立路径设计测试用例
假设:n = 5;minimum = 0;maximum = 100
路径1: 1-2-10-11-13
测试数据:value = [ 90,-999,0,0,0]
预期结果:Average = 90,total.input = 1,total.valid = 1
路径2: 1-2-10-12-13
测试数据:value = [ -999 ,0,0,0,0]
预期结果:Average = -999,total.input = 0,total.valid = 0
路径3: 1-2-3-10-11-13
测试数据:value = [ -1,90,70,-1,80]
预期结果:Average = 80,total.input = 5,total.valid = 3
路径4: 1-2-3-4-5-8-9-2-10-12-13
测试数据:value = [-1,-2,-3,-4,-999]
预期结果:Average = -999,total.input = 4,total.valid = 0
路径5: 1-2-3-4-5-6-8-9-2-10-12-13
测试数据:value = [ 120,110,101,-999,0]
预期结果:Average = -999,total.input = 3,total.valid = 0
路径6: 1-2-3-4-5-6-7-8-9-2-10-11-13
测试数据:value = [ 95,90,70,65,-999]
预期结果:Average = 80,total.input = 4, total.valid = 4
4. 基本路径覆盖测试
1. 概述
1.1 循环类型:简单循环、嵌套循环、串接循环和非结构循环
2. 简单循环的测试
2.1 零次循环:从循环入口到出口
2.2 一次循环:检查循环初始值
2.3 二次循环:检查多次循环
2.4 m次循环: 检查多次循环
2.5 最大次数循环
2.6 比最大次数多一次的循环
2.7 比最大次数少一次的循环
3. 嵌套循环的测试
3.1 先测试最内层循环:所有外层的循环变量置为最小值,最内层按简单循环测试
3.2 由里向外,测试上一层循环:测试时此层以外的所有外层循环的循环变量取最小值,此层以内的所有嵌套内层循环的循环变量取“典型”值,该层按简单循环测试
3.3 重复上一条规则,直到所有各层循环测试完毕
3.4 对全部各层循环同时取最小循环次数,或者同时取最大循环次数
4. 串接循环的测试
4.1 如果串接的各个循环互相独立,则可以分别用简单循环的方法进行测试
4.2 如果第一个循环的循环变量与第二个循环控制相关,则两个循环不独立,可使用嵌套循环的办法来测试
5. 非结构循环的测试
5.1 先将其结构化,然后再测试
5. 程序插装
1. 概述
1.1 借助向被测程序中插入操作来实现测试目的的方法
1.2 基本原理:在不破坏被测程序原有逻辑完整性的前提下,在程序的相应位置上插入一些探针
1.3 探针:采集信息的代码段(赋值语句或函数调用)
1.4 探针的执行可输出程序的运行特征数据,从而揭示程序的内部行为和特征
1.5 程序插装的主要应用:测试覆盖率度量;断言(如执行程序段后变量应满足的条件)预测;数据流异常检测
2. 测试覆盖率度量
2.1 例如,度量如下覆盖情况:程序中每个语句至少被执行一次;每个分支至少被经过一次;每个可能的路径至少被经过一次
2.2 做法:在控制流中确定一个点集,在这些点上插入软件计数器,执行一组测试用例,检查计数器的值,以便计算覆盖率
2.3 程序插装需要考虑的问题:
Ø 探测哪些信息
Ø 在程序什么部位设置探测点
Ø 需要设置多少探测点(设置最少探测点的方案)
6. 程序变异测试
1. 概述
1.1 穷尽测试是不可能的,只能选择最小的测试用例集,尽可能多地发现程序中的缺陷
1.2 变异分析是一种评价技术,通过检查测试用例能否发现特定类型缺陷对测试用例的质量进行评价
1.3 变异测试:通过注入故障(缺陷)得到相似的程序,称为变异体,使用原程序的测试用例集对变异体进行测试,如能区分变异体和原始程序,即二者的执行结果不同,则称变异体被杀死,否则变异体仍然活跃
1.4 变异体活跃的原因
Ø 测试用例集不充分
Ø 变异体与原始程序等价(即功能上是一致的)
1.5 与原始程序等价的变异体通常在测试基本完成后再区分
1.6
2. 程序变异测试实例
原始程序:
变异体Ⅰ
变异体Ⅱ
x=1;
for(i=2;i<=3;i++)
{
if(a[i] >a[x])
{
x=i;
}
}
x=1;
for(i=1;i<=3;i++)
{
if(a[i] >a[x])
{
x=i;
}
}
x=1;
for(i=1;i<=3;i++)
{
if( i >a[x])
{
x=i;
}
}
变异体Ⅲ
变异体Ⅳ
x=1;
for(i=2;i<=3;i++)
{
if(a[i]>=a[x])
︰
}
x=1;
for(i=2;i<=3;i++)
{
if( a[x] >a[x])
︰
}
原始程序测试用例集
a[1]
a[2]
a[3]
DT1
2
3
4
DT2
2
3
2
DT3
4
2
3
变异体测试结果
原始
Ⅰ
Ⅱ
Ⅲ
Ⅳ
杀死的变异体
DT1
3
3
3
3
1
Ⅳ
DT2
2
2
3
2
1
Ⅱ和Ⅳ
DT3
1
1
1
1
1
无
测试用例集的充分性
测试用例集
测试充分性
DT1
25%
DT2
50%
DT3
0%
l 增加新的测试用例DT4={2,2,1},预期结果x=1,可杀死变异体Ⅲ(其结果x=2)
l 变异体Ⅰ是等价变异体
7. 其他白盒测试
1. 数据流测试
1.1 根据程序中变量的定义(赋值)和引用位置来选择测试用例
1.2 定义-引用链DU
Ø 变量x的定义-引用链记为[x,s,s’]
Ø 其中s, s’为语句标号,变量x在s中定义(赋值),在s’中被引用,且s处定义的x 在s’处仍有效
1.3 数据流测试就是设计测试用例使得每个DU链至少被覆盖一次
1.4 数据流测试适用于嵌套IF和多重循环程序的测试
2. 域测试
2.1 一种基于程序结构的测试方法
2.2 程序错误可分为
Ø 域错误:一条执行路径对应输入域的一类,对于一个特定的输入可能执行一条错误的路径,这种错误称为域错误,或路径错误
Ø 计算性错误:对于一个特定的输入执行一条正确的路径,但由于赋值语句的错误导致输出结果不正确
Ø 丢失路径错误:由于程序中某处少了一个判定谓词而引起的错误
2.3 域测试指主要针对域错误的一种测试
2.4 域指被测程序的输入空间
2.5 输入空间可分为不同的子空间,每个子空间对应一种不同的计算
2.6 子空间的划分由程序中分支语句的谓词决定的
2.7 域测试就是在分析输入域的基础上,选择适当的测试点进行测试
2.8 域测试的缺点
Ø 对程序提出的限制过多
Ø 当程序存在很多路径时,所需的测试点也很多
3. Z路径覆盖
1. 对于一个比较复杂的程序,特别是包含循环的程序,测试不可能覆盖程序所有的路径
2. Z路径覆盖指对程序中的循环只考虑循环0次和循环1次两种情况的测试
4. 符号测试
1. 允许程序的输入可包含符号值
展开阅读全文