首页 百科知识 白盒测试技术

白盒测试技术

时间:2022-10-09 百科知识 版权反馈
【摘要】:白盒测试,又称结构测试或逻辑驱动测试,是一种透明的测试技术,它是以程序的内部逻辑结构为基础来设计测试用例的。但是这组数据只测试了判定表达式取真的情况,若实际输入的条件为假时,有错误则显然测试不出来。上述两组测试数据也同时满足判定覆盖标准。从表面上来看,它测试了所有条件的取值。下面举例说明这种测试技术。

6.2.2 白盒测试技术

白盒测试,又称结构测试或逻辑驱动测试,是一种透明的测试技术,它是以程序的内部逻辑结构为基础来设计测试用例的。其原则是:

①保证程序中每一独立的路径至少执行一次。

②保证所有判定的每一个分支至少执行一次。

③保证每个判定表达式中每个条件的所有可能结果至少出现一次。

④保证每一循环都在边界条件和一般条件至少各执行一次。

⑤验证所有内部数据结构的有效性。

下面介绍逻辑覆盖、基本路径、循环覆盖等几种典型的白盒测试技术。

一、逻辑覆盖

逻辑覆盖是指设计测试用例对程序的内部分支逻辑结构进行部分或全部覆盖的技术,这里以图6.1给出的逻辑结构为例由弱到强介绍几种逻辑覆盖技术:

img111

图6.1 程序流程图

1.语句覆盖

语句覆盖是指设计足够多的测试用例,使程序中的每条语句至少执行一次。

在图6.1所示的流程图中,如果令x=2,y=0,z=4作为测试数据,程序执行路径为abcde,使语句段1和2各执行一次,实现了语句覆盖。

但是这组数据只测试了判定表达式取真的情况,若实际输入的条件为假时,有错误则显然测试不出来。事实上,语句覆盖对程序的逻辑覆盖很少,语句覆盖只关心判定表达式的值,而没有分别测试判定表达式取不同值的情况。在上例中,为了执行abcde路径以测试每条语句,只需两个判定表达式(x>1)AND(y=0)和(x=2)OR(z>1)都取真值,上述测试数据足够满足要求。但是,若程序中第一个判断表达式中的逻辑运算符“AND”错写成“OR”,或把第二个判定表达式中的条件“z>1”误写成“z<l”,则上述测试数据就无法检测出来了。与后面所介绍的其他覆盖相比,语句覆盖是最弱的逻辑覆盖准则

2.判定覆盖

判定覆盖是指设计足够多的测试用例,使每个判定的每种可能结果都至少出现一次,也就是使每个判定的每个分支都至少执行一次。因此,判定覆盖也称为分支覆盖。

考察图6.1,只要设计测试用例通过abcde和ace,或者通过abce和acde,就能满足判定覆盖。比如,可以设计如下两组数据以满足判定覆盖:

①x=3,y=0,z=l(执行路径abce)

②x=2,y=l,z=2(执行路径acde)

判定覆盖由于各个分支都要通过,则各个分支的语句也都测试了,因此,判定覆盖必然满足语句覆盖。但是,判定覆盖的覆盖程度仍然不高。比如,错把z>l写成了z<l,则上述测试用例仍无法检测出来,因为它只覆盖了全部路径的一半。可见判定覆盖仍然很弱,但比语句覆盖强。

3.条件覆盖

条件覆盖是指设计足够多的测试用例,使每个判定表达式中的每个条件的每种可能值都至少出现一次。

仍以图6.1的程序为例,其中共有4个条件:x>1、y=0、x=2、z>l。

条件覆盖要求设计测试用例覆盖第一个判定表达式的x>1,x≤1,y=0,y≠0等各种情况,并覆盖第二个判定表达式的x=2,x≠2,z>l,z≤1等各种情况。设计如下两组测试数据,就可以满足上述条件覆盖的标准:

①x=2,y=0,z=3(覆盖x>l,y=0,x=2,z>l,执行路径abcde)

②x=l,y=l,z=l(覆盖x≤1,y≠0,x≠2,z≤1,执行路径ace)

条件覆盖一般比判定覆盖强,因为条件覆盖使判定表达式中每个条件都取到了两个不同的结果,判定覆盖却只关心整个判定表达式的值。上述两组测试数据也同时满足判定覆盖标准。但是,也可能有相反情况:虽然每个条件都取到了两个不同的结果,判定表达式却始终只取一个值。例如,若使用以下两组测试数据,则只满足条件覆盖标准,却并不满足判定覆盖标准:

①x=2,y=0,z=1(覆盖x>l,y=0,x=2,z≤l,执行路径abcde)

②x=1,y=l,z=2(覆盖x≤1,y≠0,x≠2,z>l,执行路径acde)

上述测试数据的第二个判定表达式的值总为真,不满足判定覆盖的要求,为解决这一矛盾,需要对条件和分支兼顾。

4.判定/条件覆盖

既然判定覆盖和条件覆盖互相不一定包含,于是提出了一种同时满足这两种覆盖的逻辑覆盖,那就是判定/条件覆盖。它是指设计足够多的测试用例,使得判定表达式中的每个条件都取到所有可能的值,并使每个判定表达式也都取到所有可能的判定结果。仍以图6.1的程序为例,设计以下两组测试数据:

①x=2,y=0,z=3(覆盖x>1,y=0,x=2,z>l,执行路径abcde)

②x=l,y=l,z=l(覆盖x≤1,y≠0,x≠2,z≤l,执行路径ace)

该组测试数据既满足判定覆盖又满足条件覆盖,所以满足判定/条件覆盖。其实,该组测试用例也就是上述条件覆盖的第一个例子。

判定/条件覆盖也有缺陷。从表面上来看,它测试了所有条件的取值。但实际并不是这样。因为一些条件往往掩盖了另一些条件。对于条件表达式(x>1)AND(y=0)来说,只有(x>1)的测试为真,才需测试(y=0)的值来确定此表达式的值,但是若(x>1)的测试值为假时,不需再测(y=0)的值就可确定此表达式的值为假,因而(y=0)没有被检查。同理,对于(x=2)OR(z>1)这个表达式来说,只要(x=2)测试结果为真,不必测试(z>1)的结果就可确定表达式的值为真。所以,对于判定/条件覆盖来说,逻辑表达式中的错误不一定能够查得出来。

5.条件组合覆盖

条件组合覆盖是指设计足够多的测试用例,使得每个判定表达式中条件的各种可能值的组合都至少出现一次。这是一种较强的逻辑覆盖。仍以图6.1的程序为例,两个判定表达式中各自含有两个条件,共有以下2×2×2=8种条件组合:

①x>l,y=0 ②x>l,y≠0 ③x≤1,y=0 ④x≤1,y≠0

⑤x=2,z>1⑥x=2,z≤l⑦x≠2,z>l⑧x≠2,z≤l

可以设计以下4组测试数据以满足条件组合覆盖:

①x=2,y=0,z=3,覆盖条件组合①和⑤,执行路径abcde。

②x=2,y=1,z=1,覆盖条件组合②和⑥,执行路径acde。

③x=1,y=0,z=3,覆盖条件组合③和⑦,执行路径acde。

④x=1,y=1,z=1,覆盖条件组合④和⑧,执行路径ace。

显然,满足条件组合覆盖标准的测试数据,也一定满足判定覆盖、条件覆盖和判定/条件覆盖标准。因此,条件组合覆盖是前述几种覆盖标准中最强的。但是,满足条件覆盖标准的测试数据并不一定能使程序中的每条路径都执行到,如上述四组测试数据都没有测试到路径abce。

6.路径覆盖

路径覆盖是指设计足够多的测试用例,以覆盖测试程序中所有可能的路径(若程序图中存在环,则要求每个环至少经过一次)。仍以图6.1所示的程序为例,该程序共有4条路径。设计以下4组测试数据,就可以覆盖这4条路径:

①x=2,y=0,z=3,覆盖路径abcde,覆盖条件组合①和⑤。

②x=2,y=1,z=1,覆盖路径acde,覆盖条件组合②和⑥。

③x=1,y=l,z=1,覆盖路径ace,覆盖条件组合④和⑧。

④x=3,y=0,z=l,覆盖路径abce,覆盖条件组合①和⑧。

显然,该组测试数据虽然满足路径覆盖,但是它并没有满足条件组合覆盖。

路径覆盖相对来说是相当强的逻辑覆盖标准,测试数据暴露程序错误的能力比较强,有一定的代表性,它能够保证程序中每条可能的路径都至少执行一次。但是路径覆盖并没有检验判定表达式中条件的各种组合情况,而只考虑每个判定表达式的取值组合。若把路径覆盖和条件组合覆盖结合起来,可以设计出检错能力更强的测试数据。

二、基路径测试

我们已经知道,对于比较复杂的程序进行穷尽测试往往是不可能的。基路径测试方法可以较好地解决这类问题。其关注点在于条件判定节点与循环节点对程序路径带来的复杂度的提高,通过对程序执行路径的遍历来实现对程序的覆盖。其主要思想是根据软件详细设计的过程性描述或源代码中的控制流程导出程序图(也称为程序流图),并求出程序的环形复杂性度量,然后用此度量确定程序的基路径集合,并由此导出一组测试用例来覆盖该集合中的每一条独立路径,从而可以保证程序模块的所有独立执行路径至少测试一次。下面举例说明这种测试技术。

【例6.1】案例代码如下:

int pathtest(int a,int b,int c,int x)

1 //声明循环变量

2 int i;

3 //根据变量a,b的取值对x进行赋值

4 if((a>1)&&(b<2))

5 x=c+1;

6 //再次根据变量a,x的取值对x进行赋值

7 if((a==3)||(x>3)){

8 x=x+c;

9 i=0;

10 //通过循环对x进行赋值

11 while(i<b){

12 x=x+i*c;

13 i++;

14 }

15 }

16 else{

17 x=x-c;

18 }

19 printf(“a=%d,b=%d,c=%d,x=%d\n”,a,b,c,x);

20 return x;

针对以上代码,请选择用基路径测试进行白盒测试。

基路径测试的一般步骤如下:

1.被测程序代码生成程序图

程序图是进行基路径测试的分析基础。给定待测程序代码后,第一步就是要依据代码来构造该段代码的程序图。程序图可以看成是压缩的控制流图,或者是一种特殊形式的有向图。图中节点代表语句片段,边表示控制流。程序图的特点如下:

(1)不包含注释语句。

(2)不包含数据变量的声明语句。

(3)所有连续的串行语句压缩为一个节点。

img112

图6.2 函数pathtest的程序图

以上述函数pathtest()为例,其程序图如图6.2所示。图中各字母节点代表的语句分别如下:

A:8,9

B:16,17,18

C:12,13,14

D:19,20

2.根据程序图计算环复杂度,确定基路径集合的大小

环复杂度就是McCabe复杂性度量,它是对基路径测试所得测试用例规模的粗略度量。在更多情况下,环复杂度被看成是对程序结构复杂情况的一种度量模型,该模型能够反映判定节点和循环的引入对程序结构以及执行路径数目带来的不利影响。基路径测试中,我们通过环复杂度来确定基路径集合的规模,即基路径的条数等于环复杂度的大小。

环复杂度V(G)的确定除了前面McCabe度量法中提到的方法,还有以下三种:

(1)观察法。环复杂度就是1加上程序图中封闭区域的个数。如图6.2所示,图中有3个明显的封闭区域。

①区域1:节点4、5、7所围成。

②区域2:节点7、A、11、15、D、B所围成。

③区域3:节点11、C所围成,且被包围在区域2内。

因此,图6.2所示的程序图环复杂度为4。

(2)公式法。利用公式来计算环复杂度,使利用工具来自动计算环复杂度成为现实。计算公式如下:

V(G)=e-n+2

其中,e表示图中边的数目,n表示图中节点的总数。

如图6.2所示,图中e=11,n=9,则环复杂度为4,这与直观观察的结果是一致的。

(3)判定节点法。利用代码中独立判定节点的数目来计算环复杂度,计算公式如下:

V(G)=P+1

其中,P表示图中独立判定节点的数目。

如图6.2所示,图中独立判定节点为4、7、11,共3个,所以根据这个公式计算得到的环复杂度也是4。

值得注意的是:以上计算方法仅适用于程序具有单入口、单出口的情况,如果是多出口,则需要通过修改代码,将多出口改为单出口的情况,或者在程序图中添加一个虚拟出口节点,同时将其他原始出口与该虚拟出口节点相连接,然后对修改后的程序图进行结构分析,这样才会得出正确结论。

3.利用“主路径+转向”的策略确定基路径集合

根据以上得到的环复杂度可确定基路径集合的大小,具体基路径的确定可按以下步骤:

(1)确定主路径。找到一条从程序的入口节点开始,到出口节点结束的路径,该路径应经过尽可能多的判定节点(包括循环节点),为后续的转向做准备。

(2)不断转向。每次以主路径为基础,每当碰到一个尚未转向的判定节点,就在该节点处转向一次。这里的转向是指在某个判定节点处执行一条从未执行过的判断分支,形成一条新的路径。注意:每次仅转向一个判定节点即可。这样不断转向下去,直至找到规定数量的路径。

如图6.2所示,程序图的环复杂度为4,包含3个判定节点4、7、11。则基路径集合如下所示:

●Path1:4,5,7,A,11,15,D(经过所有的判定节点)

●Path2:4,7,A,11,15,D(在判定节点4处发生转向)

●Path3:4,5,7,B,D(在判定节点7处发生转向)

●Path4:4,5,7,A,11,C,11,15,D(在判定节点11处发生转向)

为了证明得到的路径是相互独立的,表6.1给出了所有基路径及其通过的边。我们可以看到Path2、Path3和Path4都有唯一通过的边,说明这三条路径是其他路径不可替代的,必然相互独立。如果Path1依赖于其他路径,则可以用其他路径表示,但我们发现,若用其他三条路径表示Path1,则会引入新的边,也就是用灰色填充的单元格对应的边。所以可以证明Path1也是其他路径不可替代的。因此,可以得出,以上四条路径是一组相互独立的路径。

表6.1 基路径及其通过的边

img113

4.剔除不可行路径,补充其他重要的路径

以程序图为基础得到的基路径一般都是逻辑上可行的路径,不过有时候由于程序员设计程序时存在缺陷,有的会导致得到的路径实际上完全不可能执行,这种情况主要发生在判定节点串联,且前后判定节点涉及的变量之间存在一定的依赖关系的情况下。这时候我们就要结合程序分析将不可行路径剔除。同时,为了测试的完备性,我们在得到基路径集合之后,会根据以下原则补充一些重要的路径:

(1)补充执行概率较高的路径,这是最应该确保没有缺陷的路径。

(2)补充可能包含严重缺陷的路径,例如涉及空间的分配,这是从缺陷预防的角度来考虑的。

(3)补充涉及复杂算法的路径,这关系到程序最终的正确性。

以图6.2所示程序图为例,经分析,我们得到的基路径集合均是可执行路径。对于循环节点11的测试,我们在Path4的基础上补充一条路径,使得循环体执行2次。即:

Path5:4,5,7,A,11,C,11,C,11,15,D

5.根据路径集合确定测试用例,填入测试数据

根据以上的路径集合,针对每条路径设计一个测试用例,如表6.2所示。

表6.2 函数pathtest的基路径测试的测试用例

img114

基路径测试是一种使用非常广泛的白盒测试方法,其思想可借鉴用于黑盒测试中,就测试阶段而言,在集成测试、系统测试和功能测试中均可用到该方法。

三、循环结构测试

循环结构是程序的主要逻辑控制结构。要对循环结构进行穷举测试往往是不可能的。一般采用以下方法对循环结构的程序进行测试:

1.对于最多为n次的单循环,可以设计测试用例实现下列测试

①跳过循环,即一次也不执行。

②仅循环1次。

③循环2次。

④循环m次,m<n。

⑤分别循环n-l次、n次、n+1次。

2.对于嵌套循环的测试

①从最内层循环开始测试,此时外层循环都取最小值,对内层进行单循环的测试。

②向外退一层进行测试,此时其内层循环取一些典型值,其外层循环仍取最小值。

③继续向外层扩展,直至测试完成。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈