您好,欢迎访问三七文档
当前位置:首页 > IT计算机/网络 > 软件工程 > 第4章--白盒测试及其实例设计
第4章白盒测试及其实例设计4.1逻辑覆盖测试4.2路径分析测试4.3其他白盒测试方法4.4实例设计小结习题本章概述白盒测试是软件测试实践中最为有效和实用的方法之一。白盒测试是基于程序的测试,检测产品的内部结构是否合理以及内部操作是否按规定执行,覆盖测试与路径测试是其两大基本策略。本章重点围绕逻辑覆盖和路径分析展开介绍常见的白盒测试方法,并通过实例说明如何实际运用白盒测试技术。4.1逻辑覆盖测试白盒测试技术的常见方法之一就是覆盖测试,它是利用程序的逻辑结构设计相应的测试用例。测试人员要深入了解被测程序的逻辑结构特点,完全掌握源代码的流程,才能设计出恰当的用例。根据不同的测试要求,覆盖测试可以分为语句覆盖、判断覆盖、条件覆盖、判断/条件覆盖、条件组合覆盖和路径覆盖。下面是一段简单的C语言程序,作为公共程序段来说明五种覆盖测试的各自特点。程序4-1:1If(x100&&y500)then2score=score+13If(x=1000||z5000)then4score=score+5图4-1程序流程图语句覆盖语句覆盖(StatementCoverage)是指设计若干个测试用例,程序运行时每个可执行语句至少被执行一次。在保证完成要求的情况下,测试用例的数目越少越好。以下是针对公共程序段设计的两个测试用例:TestCase1:x=2000,y=600,z=6000TestCase2:x=900,y=600,z=6000判断覆盖判断覆盖(BranchCoverage)是指设计若干个测试用例,执行被测试程序时,程序中每个判断条件的真值分支和假值分支至少被执行一遍。在保证完成要求的情况下,测试用例的数目越少越好。判断覆盖又称为分支覆盖。以下是针对公共程序段设计的两个测试用例:TestCase1:x=2000,y=600,z=6000TestCase3:x=50,y=600,z=2000条件覆盖条件覆盖(ConditionCoverage)是指设计若干个测试用例,执行被测试程序时,程序中每个判断条件中的每个判断式的真值和假值至少被执行一遍。测试用例组5:TestCase6:50,600,6000TestCase7:2000,200,1000判断/条件覆盖判断/条件覆盖是指设计若干个测试用例,执行被测试程序时,程序中每个判断条件的真假值分支至少被执行一遍,并且每个判断条件的内部判断式的真假值分支也要被执行一遍。测试用例组6:TestCase1:x=2000,y=600,z=2000TestCase6:x=2000,y=200,z=6000TestCase7:x=2000,y=600,z=2000TestCase8:x=50,y=200,z=2000条件组合覆盖条件组合覆盖是指设计若干个测试用例,执行被测试程序时,程序中每个判断条件的的内部判断式的各种真假组合可能都至少被执行一遍。可见,满足条件组合覆盖的测试用例组一定满足判断覆盖、条件覆盖和判断/条件覆盖。测试用例组7:TestCase1:x=2000,y=600,z=2000TestCase6:x=2000,y=200,z=6000TestCase7:x=2000,y=600,z=2000TestCase8:x=50,y=200,z=2000路径覆盖路径覆盖(PathCoverage)要求设计若干测试用例,执行被测试程序时,能够覆盖程序中所有的可能路径。测试用例组8:TestCase1:x=2000,y=600,z=6000TestCase3:x=50,y=600,z=2000TestCase4:x=2000,y=600,z=2000TestCase7:x=2000,y=200,z=1000应该注意的是,上面6种覆盖测试方法所引用的公共程序只有短短4行,是一段非常简单的示例代码。然而在实际测试程序中,一个简短的程序,其路径数目是一个庞大的数字。要对其实现路径覆盖测试是很难的。所以,路径覆盖测试是相对的,尽可能把路径数压缩到一个可承受范围。当然,即便对某个简短的程序段做到了路径覆盖测试,也不能保证源代码不存在其他软件问题了。其他的软件测试手段也必要的,它们之间是相辅相成的。没有一个测试方法能够找尽所有软件缺陷,只能说是尽可能多地查找软件缺陷。4.2路径分析测试4.2.1控制流图白盒测试是针对软件产品内部逻辑结构进行测试的,测试人员必须对测试中的软件有深入的理解,包括其内部结构、各单元部分及之间的内在联系,还有程序运行原理等等。因而这是一项庞大并且复杂的工作。为了更加突出程序的内部结构,便于测试人员理解源代码,可以对程序流程图进行简化,生成控制流图(ControlFlowGraph)。简化后的控制流图是由节点和控制边组成的。控制流图有以下几个特点:具有唯一入口节点,即源节点,表示程序段的开始语句;具有唯一出口节点,即汇节点,表示程序段的结束语句;节点由带有标号的圆圈表示,表示一个或多个无分支的源程序语句;控制边由带箭头的直线或弧表示,代表控制流的方向。图4-2常见的控制流图程序环路复杂性程序的环路复杂性是一种描述程序逻辑复杂度的标准,该标准运用基本路径方法,给出了程序基本路径集中的独立路径条数,这是确保程序中每个可执行语句至少执行一次所必需的测试用例数目的上界。给定一个控制流图G,设其环形复杂度为V(G),在这里介绍三种常见的计算方法来求解V(G)。(1)V(G)=E-N+2,其中E是控制流图G中边的数量,N是控制流图中节点的数目。(2)V(G)=P+1,其中P是控制流图G中判断节点的数目。(3)V(G)=A,其中A是控制流图G中区域的数目。由边和结点围成的区域叫做区域,当在控制流图中计算区域的数目时,控制流图外的区域也应记为一个区域。4.2.2独立路径测试从前面学过的覆盖测试一节中可知,对于一个较为复杂的程序要做到完全的路径覆盖测试是不可能实现的。既然路径覆盖测试无法达到,那么可以对某个程序的所有独立路径进行测试,也就是说检验了程序的每一条语句,从而达到语句覆盖,这种测试方法就是独立路径测试方法。从控制流图来看,一条独立路径是至少包含有一条在其它独立路径中从未有过的边的路径。路径可以用控制流图中的节点序列来表示。例如,在如图4-3所示的控制流图中,一组独立的路径是path1:1-11path2:1-2-3-4-5-10-1-11path3:1-2-3-6-8-9-10-1-11path4:1-2-3-6-7-9-10-1-11路径path1,path2,path3,path4组成了控制流图的一个基本路径集。图4-3控制流图示例独立路径测试的步骤包括3个方面:导出程序控制流图求出程序环形复杂度设计测试用例(TestCase)程序4-2:1main()2{3intnum1=0,num2=0,score=100;4inti;5charstr;6scanf(“%d,%c\n”,&i,&str);7while(i5)8{9if(str=’T’)10num1++;11elseif(str=’F’)12{13score=score-10;14num2++;15}16i++;17}18printf(“num1=%d,num2=%d,score=%d\n”,num1,num2,score);19}1.导出程序控制流图根据源代码可以导出程序的控制流图,如图4-4所示。每个圆圈代表控制流图的节点,可以表示一个或多个语句。圆圈中的数字对应程序中某一行的编号。箭头代表边的方向,即控制流方向。图4-4程序4-2的控制流图2.求出程序环形复杂度根据程序环形复杂度的计算公式,求出程序路径集合中的独立路径数目。公式1:V(G)=10-8+2,其中10是控制流图G中边的数量,8是控制流图中节点的数目。公式2:V(G)=3+1,其中3是控制流图G中判断节点的数目。公式3:V(G)=4,其中4是控制流图G中区域的数目。因此,控制流图G的环形复杂度是4。就是说至少需要4条独立路径组成基本路径集合,并由此得到能够覆盖所有程序语句的测试用例。3.设计测试用例根据上面环形复杂度的计算结果,源程序的基本路径集合中有4条独立路径:路径1:7-18路径2:7-9-10-16-7-18路径3:7-9-11-15-16-7-18路径4:7-9-11-13-14-15-16-7-18根据上述4条独立路径,设计了测试用例组9,如表4-9所示。测试用例组9中的4个测试用例作为程序输入数据,能够遍历这4条独立路径。对于源程序中的循环体,测试用例组9中的输入数据使其执行零次或一次。表4-9测试用例组9测试用例输入期望输出执行路径istrnum1num2scoreTestCase15‘T’00100路径1TestCase24‘T’10100路径2TestCase34‘A’00100路径3TestCase44‘F’0190路径4程序4-3:1if(aorb)2then3procedurex4else5procedurey;6……对应的控制流图如图4-5所示,程序行1的a,b都是独立的判断节点,还有程序行4也是判断节点,所以共计3个判断节点。图4-5的环形复杂度为V(G)=3+1,其中3是图4-5中判断节点的数目。图4-5程序4-3的控制流图4.2.3Z路径覆盖测试Z路径覆盖是路径覆盖面的一种变体。对于语句较少的简单程序,路径覆盖是具有可行性的。但是对于源代码很多的复杂程序,或者对于含有较多条件语句和较多循环体的程序来说,需要测试的路径数目会成倍增长,达到一个巨大数字,以至于无法实现路径覆盖。为了解决这一问题,采用简化循环方法的路径覆盖就是Z路径覆盖。所谓简化循环就是减少循环的次数。不考虑循环体的形式和复杂度如何,也不考虑循环体实际上需要执行多少次,只考虑通过循环体零次和一次这两种情况。这里的零次循环是指跳过循环体,从循环体的入口直接到循环体的出口。通过一次循环体是指检查循环初始值。如图4-6(a)和图4-6(b)所示表示了两种最典型的循环控制结构。图4-6(a)是先比较循环条件后执行循环体,循环体B可能执行也可能不被执行。限定循环体B执行零次和一次,这样就和图4-6(c)的条件结构一样了。图4-6(b)是先执行循环体后比较循环条件。假设循环体B被执行一次,在经过条件判断跳出循环,那么其效果就和图4-6(c)的条件结构只执行右分支的效果一样了。一旦将循环结构简化为选择结构后,路径的数量将大大减少,这样就可以实现路径覆盖测试了。对于实现简化循环的程序,可以将程序用路径树来表示。当得到某一程序的路径树后,从其根节点开始,一次遍历,再回到根节点时,将所经历的叶节点名排列起来,就得到一个路径。如果已经遍历了所有叶子节点,那就得到了所有的路径。当得到所有的路径后,生成每个路径的测试用例,就可以实现Z路径覆盖测试。图4-6循环结构和条件结构4.3其他白盒测试方法4.3.1循环测试循环测试是一种着重循环结构有效性测试的白盒测试方法。循环结构测试用例的设计有以下4种模式,如图4-7所示。图4-7循环测试的模式4.3.2变异测试变异测试是一种故障驱动测试,即针对某一类特定程序故障进行的测试,变异测试也是一种比较成熟的排错性测试方法。它可以通过检验测试数据集的排错能力来判断软件测试的充分性。假设对程序P进行一些微小改动而得到程序MP,程序MP就是程序P的一个变异体。假设程序P在测试集T上是正确的,设计某一变异体集合:M={MP|MP是P的变异体},若变异体集合M中的每一个元素在T上都存在错误,则认为源程序P的正确度较高,否则若M中的某些元素在T上运行正确,则可能存在以下一些情况:•M中的这些变异体在功能上与源程序P是等价的;•现有的测试数据不足以找出源程序P与其变异体之间的差别;•源程序P可能产生故障,而其某些变异体却是正确的。可见,测试集T和变异体集合M中的每一个变异体MP的选择都是很重要的,它们会直接影响变异测试的测试效果。总之,对程序进行变换的方法多种多样,具体操作要靠测试人员的实际经验。
本文标题:第4章--白盒测试及其实例设计
链接地址:https://www.777doc.com/doc-5073937 .html