1、白盒测试,白盒测试,白盒测试概念测试覆盖标准逻辑驱动测试基本路径测试,白盒测试概念,白盒测试也称结构测试或逻辑驱动测试,是一种测试用例设计方法,它从程序的控制结构导出测试用例。(测试用例由测试输入数据以及与之对应的输出结果组成。 测试用例设计的好坏直接决定了测试的效果和结果。所以说在软件测试活动中最关键的步骤就是设计有效的测试用例。)白盒测试使用被测单元内部如何工作的信息,允许测试人员对程序内部逻辑结构及有关信息来设计和选择测试用例,对程序的逻辑路径进行测试。基于一个应用代码的内部逻辑知识,测试是基于覆盖全部代码、分支、路径、条件。,白盒测试的主要目的:,保证一个模块中的所有独立路径至少被执行
2、一次;对所有的逻辑值均需要测试真、假两个分支;在上下边界及可操作范围内运行所有循环;检查内部数据结构以确保其有效性。,测试覆盖标准,白盒法特点:以程序的内部逻辑为基础设计测试用例,所以又称为逻辑覆盖法。应用白盒法时,手头必须有程序的规格说明以及程序清单。 白盒法考虑的是测试用例对程序内部逻辑的覆盖程度。最彻底的白盒法是覆盖程序中的每一条路径,但是由于程序中一般含有循环,所以路径的数目极大,要执行每一条路径是不可能的,只能希望覆盖的程度尽可能高些。,测试覆盖标准,测试覆盖标准,上页小程序的流程图,其中包括了一个执行达20次的循环。那么它所包含的不同执行路径数高达520(1013)条,若要对它进行
3、穷举测试,覆盖所有的路径。假使测试程序对每一条路径进行测试需要1毫秒,同样假定一天工作24小时,一年工作365 天, 那么要想把如图所示的小程序的所有路径测试完,则需要3170年。,测试覆盖标准,为了衡量测试的覆盖程度,需要建立一些标准,目前常用的一些覆盖标准从低到高分别是: 语句覆盖:是一个比较弱的测试标准,它的含义是:选择足够的测试用例,使得程序中每个语句至少都能被执行一次。 它是最弱的逻辑覆盖,效果有限,必须与其它方法交互使用。,测试覆盖标准,判定覆盖(也称为分支覆盖):执行足够的测试用例,使得程序中的每一个分支至少都通过一次。 判定覆盖只比语句覆盖稍强一些,但实际效果表明,只是判定覆盖
4、,还不能保证一定能查出在判断的条件中存在的错误。因此,还需要更强的逻辑覆盖准则去检验判断内部条件。条件覆盖:执行足够的测试用例,使程序中每个判断的每个条件的每个可能取值至少执行一次; 条件覆盖深入到判定中的每个条件,但可能不能满足判定覆盖的要求。,测试覆盖标准,判定/条件覆盖:执行足够的测试用例,使得判定中每个条件取到各种可能的值,并使每个判定取到各种可能的结果。 判定/条件覆盖有缺陷。从表面上来看,它测试了所有条件的取值。但是事实并非如此。往往某些条件掩盖了另一些条件。会遗漏某些条件取值错误的情况。为彻底地检查所有条件的取值,需要将判定语句中给出的复合条件表达式进行分解,形成由多个基本判定嵌
5、套的流程图。这样就可以有效地检查所有的条件是否正确了。,测试覆盖标准,条件组合覆盖:执行足够的例子,使得每个判定中条件的各种可能组合都至少出现一次。 这是一种相当强的覆盖准则,可以有效地检查各种可能的条件取值的组合是否正确。它不但可覆盖所有条件的可能取值的组合,还可覆盖所有判断的可取分支,但可能有的路径会遗漏掉。测试还不完全。,白盒测试的主要方法:,逻辑驱动测试语句覆盖:语句覆盖就是设计若干个测试用例,运行被测试程序,使得每一条可执行语句至少执行一次;判定覆盖(也称为分支覆盖):设计若干个测试用例,运行所测程序,使程序中每个判断的取真分支和取假分支至少执行一次;条件覆盖:设计足够多的测试用例,
6、运行所测程序,使程序中每个判断的每个条件的每个可能取值至少执行一次;判定/条件覆盖:设计足够多的测试用例,运行所测程序,使程序中每个判断的每个条件的所有可能取值至少执行一次,并且每个可能的判断结果也至少执行一次,换句话说,即是要求各个判断的所有可能的条件取值组合至少执行一次;,白盒测试的主要方法:,条件组合覆盖:设计足够多的测试用例,运行所测程序,使程序中每个判断的所有可能的条件取值组合至少执行一次;基本路径测试设计足够多的测试用例,运行所测程序,要覆盖程序中所有可能的路径。这是最强的覆盖准则。但在路径数目很大时,真正做到完全覆盖是很困难的,必须把覆盖路径数目压缩到一定限度。,语句覆盖,语句覆
7、盖”是一个比较弱的测试标准,它的含义是:选择足够的测试用例,使得程序中每个语句至少都能被执行一次。 如,例1:PROCEDUREM(VAR A,B,X:REAL);BEGIN IF (A1) AND (B=0) THEN X:=X/A; IF (A=2) OR (X1) THEN X:=X+1; END.,语句覆盖,为使程序中每个语句至少执行一次,只需设计一个能通过路径ace的例子就可以了,例如选择输入数据为: A=2,B=0,X=3 就可达到“语句覆盖”标准。,语句覆盖,语句覆盖,从上例可看出,语句覆盖实际上是很弱的,如果第一个条件语句中的AND错误地编写成OR,上面的测试用例是不能发现这个
8、错误的;又如第三个条件语句中X1误写成X0,这个测试用例也不能暴露它,此外,沿着路径abd执行时,X的值应该保持不变,如果这一方面有错误,上述测试数据也不能发现它们。,分支覆盖,比“语句覆盖”稍强的覆盖标准是“分支覆盖”(或称分支覆盖)标准。含义是:执行足够的测试用例,使得程序中的每一个分支至少都通过一次。,分支覆盖,对例1的程序,如果设计两个例子,使它们能通过路径ace和abd,或者通过路径acd和abe,就可达到“判定覆盖”标准,为此,可以选择输入数据为: A=3,B=0,X=1 (沿路径acd执行); A=2,B=1,X=3(沿路径abe执行),分支覆盖,判定覆盖,判定覆盖,A=3,B=
9、0,X=1 (沿路径acd执行)A=2,B=1,X=3 (沿路径abe执行),分支覆盖,程序中含有判定的语句包括IF-THEN-ELSE、DO-WHILE、REPEAT-UNTIL等,除了双值的判定语句外,还有多值的判定语句,如PASCAL中的CASE语句、FORTRAN中带有三个分支的IF语句等。所以“分支覆盖”更一般的含义是:使得每一个分支获得每一种可能的结果。 “分支覆盖”比“语句覆盖”严格,因为如果每个分支都执行过了,则每个语句也就执行过了。但是,“分支覆盖”还是很不够的,例如例1两个测试用例未能检查沿着路径abd执行时,X的值是否保持不变。,条件覆盖,一个判定中往往包含了若干个条件,
10、如例1的程序中,判定 (A1) AND (B=0)包含了两个条件: A1以及 B=0,所以可引进一个更强的覆盖标准“条件覆盖”。“条件覆盖”的含义是:执行足够的测试用例,使得判定中的每个条件获得各种可能的结果。,条件覆盖,例1的程序有四个条件: A1、 B=0、A=2、X1 为了达到“条件覆盖”标准,需要执行足够的测试用例使得在a点有: A1、A1、B=0、B0 等各种结果出现,以及在b点有: A=2、A2、X1、X1 等各种结果出现。现在只需设计以下两个测试用例就可满足这一标准: A=2,B=0,X=4(沿路径ace执行); A=1,B=1,X=1 (沿路径abd执行)。,条件覆盖,条件覆盖
11、,条件覆盖,A=2,B=0,X=4(沿路径ace执行)A=1,B=1,X=1 (沿路径abd执行),条件覆盖,“条件覆盖”通常比“分支覆盖”强,因为它使一个判定中的每一个条件都取到了两个不同的结果,而判定覆盖则不保证这一点。“条件覆盖”并不包含“分支覆盖”,如对语句IF(A AND B)THEN S 设计测试用例使其满足条件覆盖,即使A为真并使B为假,以及使A为假而且B为真,但是它们都未能使语句S得以执行。,分支/条件覆盖,针对上面的问题引出了另一种覆盖标准“分支 条件覆盖”,它的含义是:执行足够的测试用例,使得分支中每个条件取到各种可能的值,并使每个分支取到各种可能的结果。对例1的程序,前面
12、的两个例子 A=2,B=0,X=4 (沿ace路) A=1,B=1,X=1 (沿abd路径)是满足这一标准的。,条件组合覆盖,针对上述问题又提出了另一种标准“条件组合覆盖”。它的含义是:执行足够的例子,使得每个判定中条件的各种可能组合都至少出现一次。显然,满足“条件组合覆盖”的测试用例是一定满足“分支覆盖”、“条件覆盖”和“分支/条件覆盖”的。,条件组合覆盖,再看例1的程序,我们需要选择适当的例子,使得下面 8种条件组合都能够出现:1)A1, B=02)A1, B03)A1, B=0 4) A1, B05) A=2, X1 6) A=2,X1 7) A2, X1 8) A2, X1 5)、 6
13、)、 7)、8)四种情况是第二个 IF语句的条件组合,而X的值在该语句之前是要经过计算的,所以还必须根据程序的逻辑推算出在程序的入口点X的输入值应是什么。,条件组合覆盖,下面设计的四个例子可以使上述 8种条件组合至少出现一次: A=2,B=0,X=4 使 1)、5)两种情况出现; A=2,B=1,X=1 使 2)、6)两种情况出现; A=1,B=0,X=2 使 3)、7)两种情况出现; A=1,B=1,X=1 使 4)、8)两种情况出现。,条件组合覆盖,上面四个例子虽然满足条件组合覆盖,但并不能覆盖程序中的每一条路径,例如路径acd就没有执行,因此,条件组合覆盖标准仍然是不彻底。,路径测试,路
14、径测试就是设计足够多的测试用例,覆盖被测试对象中的所有可能路径。 对于例1,下面的测试用例则可对程序进行全部的路径覆盖。,基本路径测试,例1、例2都是很简单的程序函数,只有四条路径。但在实践中,一个不太复杂的程序,其路径都是一个庞大的数字,要在测试中覆盖所有的路径是不现实的。为了解决这一难题,只得把覆盖的路径数压缩到一定限度内,例如,程序中的循环体只执行一次。 下面介绍的基本路径测试就是这样一种测试方法,它在程序控制图的基础上,通过分析控制构造的环行复杂性,导出基本可执行路径集合,从而设计测试用例的方法。设计出的测试用例要保证在测试中程序的每一个可执行语句至少执行一次。,基本路径测试,前提条件
15、 测试进入的前提条件是在测试人员已经对被测试对象有了一定的了解,基本上明确了被测试软件的逻辑结构。测试过程 过程是通过针对程序逻辑结构设计和加载测试用例,驱动程序执行,以对程序路径进行测试。测试结果是分析实际的测试结果与预期的结果是否一致。,基本路径测试,在程序控制流图的基础上,通过分析控制构造的环路复杂性,导出基本可执行路径集合,从而设计测试用例。包括以下4个步骤和一个工具方法:程序的控制流图:描述程序控制流的一种图示方法。程序圈复杂度:McCabe复杂性度量。从程序的环路复杂性可导出程序基本路径集合中的独立路径条数,这是确定程序中每个可执行语句至少执行一次所必须的测试用例数目的上界。导出测
16、试用例:根据圈复杂度和程序结构设计用例数据输入和预期结果。准备测试用例:确保基本路径集中的每一条路径的执行。,基本路径测试,工具方法: 图形矩阵:是在基本路径测试中起辅助作用的软件工具,利用它可以实现自动地确定一个基本路径集。,控制流图的符号,在介绍基本路径方法之前,必须先介绍一种简单的控制流表示方法,即流图。流图是对待测试程序过程处理的一种表示。流图使用下面的符号描述逻辑控制流,每一种结构化构成元素有一个相应的流图符号。,控制流图,流图只有二种图形符号图中的每一个圆称为流图的结点,代表一条或多条语句。流图中的箭头称为边或连接,代表控制流。任何过程设计都要被翻译成控制流图。,控制流图,在将程序
17、流程图简化成控制流图时,应注意:在选择或多分支结构中,分支的汇聚处应有一个汇聚结点。边和结点圈定的区域叫做区域,当对区域计数时,图形外的区域也应记为一个区域。如下页图所示,控制流图,控制流图,如果判断中的条件表达式是由一个或多个逻辑运算符 (OR, AND, NAND, NOR) 连接的复合条件表达式,则需要改为一系列只有单条件的嵌套的判断。例如: 1 if a or b 2 x 3 else 4 y对应的逻辑为:,独立路径,独立路径:至少沿一条新的边移动的路径,1,7,6,2,3,8,9,10,11,4,5,路径1:1-11路径2:1-2-3-4-5-10-1-11路径3:1-2-3-6-8
18、-9-10-1-11路径4:1-2-3-6-7-9-10-1-11,对以上路径的遍历,就是至少一次地执行了程序中的所有语句。,基本路径测试,第一步:画出控制流图 流程图用来描述程序控制结构。可将流程图映射到一个相应的流图(假设流程图的菱形决定框中不包含复合条件)。在流图中,每一个圆,称为流图的结点,代表一个或多个语句。一个处理方框序列和一个菱形决测框可被映射为一个结点,流图中的箭头,称为边或连接,代表控制流,类似于流程图中的箭头。一条边必须终止于一个结点,即使该结点并不代表任何语句(例如:if-else-then结构)。由边和结点限定的范围称为区域。计算区域时应包括图外部的范围。,基本路径测试
19、,画出其程序流程图和对应的控制流图如下,基本路径测试 - 计算圈复杂度,第二步:计算圈复杂度圈复杂度是一种为程序逻辑复杂性提供定量测度的软件度量,将该度量用于计算程序的基本的独立路径数目,为确保所有语句至少执行一次的测试数量的上界。独立路径必须包含一条在定义之前不曾用到的边。有以下三种方法计算圈复杂度:流图中区域的数量对应于环型的复杂性;给定流图G的圈复杂度V(G),定义为V(G)=E-N+2,E是流图中边的数量,N是流图中结点的数量;给定流图G的圈复杂度V(G),定义为V(G)=P+1,P是流图G中判定结点的数量。,基本路径测试 - 计算圈复杂度,对应上面图中的圈复杂度,计算如下:流图中有四
20、个区域;V(G)=10条边-8结点+2=4;V(G)=3个判定结点+1=4。,基本路径测试 - 导出测试用例,第三步:导出测试用例 根据上面的计算方法,可得出四个独立的路径。(一条独立路径是指,和其他的独立路径相比,至少引入一个新处理语句或一个新判断的程序通路。V(G)值正好等于该程序的独立路径的条数。)路径1:4-14路径2:4-6-7-14路径3:4-6-8-10-13-4-14路径4:4-6-8-11-13-4-14根据上面的独立路径,去设计输入数据,使程序分别执行到上面四条路径。,基本路径测试 - 准备测试用例,第四步:准备测试用例 为了确保基本路径集中的每一条路径的执行,根据判断结点
21、给出的条件,选择适当的数据以保证某一条路径可以被测试到,满足上面例子基本路径集的测试用例是:,基本路径测试再举例,例5:下例程序流程图描述了最多输入50个值(以1作为输入结束标志),计算其中有效的学生分数的个数、总分数和平均值。,步骤1:导出过程的流图。,步骤2:确定环形复杂性度量V(G):1)V(G)= 6 (个区域)2)V(G)=EN+2=1612+2=6 其中E为流图中的边数,N为结点数;3)V(G)=P+1=5+1=6 其中P为谓词结点的个数。在流图中,结点2、3、5、6、9是谓词结点。,基本路径测试再举例,基本路径测试再举例,步骤3:确定基本路径集合(即独立路径集合)。于是可确定6条
22、独立的路径:路径1:1-2-9-10-12路径2:1-2-9-11-12路径3:1-2-3-9-10-12路径4:1-2-3-4-5-8-2路径5:1-2-3-4-5-6-8-2路径6:1-2-3-4-5-6-7-8-2,基本路径测试再举例,步骤4:为每一条独立路径各设计一组测试用例,以便强迫程序沿着该路径至少执行一次。1)路径1(1-2-9-10-12)的测试用例: scorek=有效分数值,当k i ; scorei=1, 2i50; 期望结果:根据输入的有效分数算出正确的分数个数n1、总分sum和平均分average。,基本路径测试再举例,2)路径2(1-2-9-11-12)的测试用例:
23、 score 1 = 1 ; 期望的结果:average = 1 ,其他量保持初值。3)路径3(1-2-3-9-10-12)的测试用例: 输入多于50个有效分数,即试图处理51个分数,要求前51个为有效分数;期望结果:n1=50、且算出正确的总分和平均分。,基本路径测试再举例,4)路径4(1-2-3-4-5-8-2)的测试用例: scorei=有效分数,当i100,k i ;期望结果:根据输入的有效分数算出正确的分数个数n1、总分sum和平均分average。,基本路径测试再举例,6)路径6(1-2-3-4-5-6-7-8-2)的测试用例: scorei=有效分数, 当i3) /语句块3,ht
24、tp:/ 电子发烧友 http:/ 电子技术论坛,逻辑覆盖法(续),http:/ 电子发烧友 http:/ 电子技术论坛,语句覆盖,要实现DoWork函数的语句覆盖,只需设计一个测试用例就可以覆盖程序中的所有可执行语句。测试用例输入为: x=4、y=5、z=5 程序执行的路径是:abd分析: 语句覆盖可以保证程序中的每个语句都得到执行,但发现不了判定中逻辑运算的错误,即它并不是一种充分的检验方法。例如在第一个判定(x3)&(z5错误写为y3)&(z3 取真值记为T1,取假值记为-T1 条件z5) ): 条件x=4 取真值记为T3,取假值记为-T3 条件y5 取真值记为T4,取假值记为-T4,h
25、ttp:/ 电子发烧友 http:/ 电子技术论坛,条件覆盖(续),根据条件覆盖的基本思想,要使上述4个条件可能产生的8种情况至少满足一次,设计测试用例如下:,分析:上面这组测试用例不但覆盖了4个条件的全部8种情况,而且将两个判定的4个分支b、c、d、e也同时覆盖了,即同时达到了条件覆盖和判定覆盖。,http:/ 电子发烧友 http:/ 电子技术论坛,条件覆盖(续),说明:虽然前面的一组测试用例同时达到了条件覆盖和判定覆盖,但是,并不是说满足条件覆盖就一定能满足判定覆盖。如果设计了下表中的这组测试用例,则虽然满足了条件覆盖,但只是覆盖了程序中第一个判定的取假分支c 和第二个判定的取真分支d,
26、不满足判定覆盖的要求。,http:/ 电子发烧友 http:/ 电子技术论坛,判定/条件覆盖,判定/条件覆盖实际上是将判定覆盖和条件覆盖结合起来的一种方法,即:设计足够的测试用例,使得判定中每个条件的所有可能取值至少满足一次,同时每个判定的可能结果也至少出现一次。根据判定/条件覆盖的基本思想,只需设计以下两个测试用例便可以覆盖4个条件的8种取值以及4个判定分支。,http:/ 电子发烧友 http:/ 电子技术论坛,判定/条件覆盖(续),分析:从表面上看,判定/条件覆盖测试了各个判定中的所有条件的取值,但实际上,编译器在检查含有多个条件的逻辑表达式时,某些情况下的某些条件将会被其它条件所掩盖。
27、因此,判定/条件覆盖也不一定能够完全检查出逻辑表达式中的错误。 例如:对于第一个判定(x3)&(z3和z3为假,则编译器将不再检查z5)来说,若条件x=4满足,就认为该判定为真,这时将不会再检查y5,那么同样也无法发现这个条件中的错误。,http:/ 电子发烧友 http:/ 电子技术论坛,组合覆盖,组合覆盖的目的是要使设计的测试用例能覆盖每一个判定的所有可能的条件取值组合。对DoWork函数中的各个判定的条件取值组合加以标记: 1、x3, z3, z=10 记做T1 -T2,第一个判定的取假分支 3、x=10 记做-T1 -T2,第一个判定的取假分支 5、x=4, y5 记做T3 T4,第二
28、个判定的取真分支 6、x=4, y5 记做-T3 T4,第二个判定的取真分支 8、x!=4, y=5 记做-T3 -T4,第二个判定的取假分支,http:/ 电子发烧友 http:/ 电子技术论坛,组合覆盖(续),根据组合覆盖的基本思想,设计测试用例如下:,分析:上面这组测试用例覆盖了所有8种条件取值的组合,覆盖了所有判定的真假分支,但是却丢失了一条路径abe。,http:/ 电子发烧友 http:/ 电子技术论坛,路径覆盖,前面提到的5种逻辑覆盖都未涉及到路径的覆盖。事实上,只有当程序中的每一条路径都受到了检验,才能使程序受到全面检验。路径覆盖的目的就是要使设计的测试用例能覆盖被测程序中所有
29、可能的路径。根据路径覆盖的基本思想,在满足组合覆盖的测试用例中修改其中一个测试用例,则可以实现路径覆盖:,http:/ 电子发烧友 http:/ 电子技术论坛,路径覆盖(续),分析:虽然前面一组测试用例满足了路径覆盖,但并没有覆盖程序中所有的条件组合(丢失了组合3和7),即满足路径覆盖的测试用例并不一定满足组合覆盖。说明:对于比较简单的小程序,实现路径覆盖是可能做到的。但如果程序中出现较多判断和较多循环,可能的路径数目将会急剧增长,要在测试中覆盖所有的路径是无法实现的。为了解决这个难题,只有把覆盖路径数量压缩到一定的限度内,如程序中的循环体只执行一次。在实际测试中,即使对于路径数很有限的程序已
30、经做到路径覆盖,仍然不能保证被测试程序的正确性,还需要采用其他测试方法进行补充。,http:/ 电子发烧友 http:/ 电子技术论坛,习题,为以下流程图所示的程序段设计一组测试用例,要求分别满足语句覆盖、判定覆盖、条件覆盖、判定/条件覆盖、组合覆盖和路径覆盖。,http:/ 电子发烧友 http:/ 电子技术论坛,4.3.3 面向对象的覆盖,继承上下文覆盖由于传统的结构化度量没有考虑面向对象的一些特性(如多态、继承和封装等),所以在面向对象领域,传统的结构化覆盖必须被加强,以满足面向对象特性。继承上下文覆盖考虑在每个类的上下文内获得的覆盖率级别。它是扩展到面向对象领域里的一种覆盖率度量方法,
31、用于度量在系统中的多态调用被测试得多好。继承上下文定义将基类上下文内例行程序的执行作为独立于继承类上下文内例行程序的执行。同样,它们在考虑继承类上下文内例行程序的执行也独立于基类上下文内例行程序的执行。为了获得100继承上下文覆盖,代码必须在每个适当的上下文内被完全执行。,http:/ 电子发烧友 http:/ 电子技术论坛,面向对象的覆盖(续),基于状态的上下文覆盖在绝大多数面向对象的系统中存在这样的一些类:这些类的对象可以存在于众多不同状态中的任何一种,并且由于类的行为依赖于状态,每个类的行为在每个可能的状态中其性质是不同的。基于状态的上下文覆盖对应于被测类对象的潜在状态。这样基于状态的上下文覆盖把一个状态上下文内的一个例行程序的执行认为是独立于另一个状态内相同例行程序的执行。为了达到100的基于状态的上下文覆盖,例行程序必须在每个适当的上下文(状态)内被执行。,