1白盒测试用例设计方法1.1白盒测试简介白盒测试又称结构测试、逻辑驱动测试或基于程序的测试,一般多发生在单元测试阶段。
白盒测试方法主要包括逻辑覆盖法,基本路径法,程序插装等。
这里重点介绍一下常用的基本路径法,对于逻辑覆盖简单介绍一下覆盖准则。
1.2基本路径法在程序控制流图的基础上,通过分析控制构造的环路复杂性,导出独立路径集合,从而设计测试用例,设计出的测试用例要保证在测试中程序的每一个可执行语句至少执行一次。
在介绍基本路径测试方法(又称独立路径测试)之前,先介绍流图符号:图1如图1所示,每一个圆,称为流图的节点,代表一个或多个语句,流程图中的处理方框序列和菱形决策框可映射为一个节点,流图中的箭头,称为边或连接,代表控制流,类似于流程图中的箭头。
一条边必须终止于一个节点,即使该节点并不代表任何语句,例如,图2中两个处理方框交汇处是一个节点,边和节点限定的范围称为区域。
图2任何过程设计表示法都可被翻译成流图,下面显示了一段流程图以及相应的流图。
注意,程序设计中遇到复合条件时(逻辑or, and, nor 等),生成的流图变得更为复杂,如(c)流图所示。
此时必须为语句IF a OR b 中的每一个a 和b 创建一个独立的节点。
(c)流图独立路径是指程序中至少引进一个新的处理语句集合,采用流图的术语,即独立路径必须至少包含一条在定义路径之前不曾用到的边。
例如图(b)中所示流图的一个独立路径集合为:路径1:1-11路径2:1-2-3-4-5-10-1-11路径3:1-2-3-6-8-9-10-1-11路径4:1-2-3-6-7-9-10-1-11上面定义的路径1,2,3 和4 包含了(b)流图的一个基本集,如果能将测试设计为强迫运行这些路径,那么程序中的每一条语句将至少被执行一次,每一个条件执行时都将分别取true 和false(分支覆盖)。
应该注意到基本集并不唯一,实际上,给定的过程设计可派生出任意数量的不同基本集。
如何才能知道需要寻找多少条路径呢?可以通过如下三种方法之一来计算独立路径的上界:1. V=E-N+2,E 是流图中边的数量,N 是流图节点数量。
2. V=P+1,P 是流图中判定节点的数量3. V=R,R 是流图中区域的数量例如,(b)流图可以采用上述任意一种算法来计算独立路径的数量1. V=11 条边-9 个节点+2=42. V=3 个判定节点+1=43. 流图有4 个区域,所以V=4由此为了覆盖所有程序语句,必须设计至少4 个测试用例使程序运行于这4 条路径。
在采用基本路径测试方法中,获取测试用例可参考以下方式:⏹通过非路径分析得到的测试用例;⏹找到尚未测试过的路径并生成相应的测试用例;⏹指定特定路径生成相应的测试用例。
⏹对程序中的循环作了执行了零次和一次的限制,这样程序路径的数目就是有限的。
⏹如果程序的数目有限,就可采用枚举法得到所有的路径。
⏹完成若干测试用例后,就可以知道所测路径是哪些,尚有哪些待测路径。
⏹在指出要测试的路径以后,可以自动生成相应的测试用例。
1.3逻辑覆盖1.3.1循环测试简介逻辑覆盖是以程序内部的逻辑结构为基础的设计测试用例的技术。
它的主要方法有:语句覆盖;判定覆盖;条件覆盖;判定—条件覆盖;条件组合覆盖;路径覆盖。
举例如下:1.3.2语句覆盖语句覆盖:语句覆盖就是设计若干个测试用例,运行被测程序,使得每一可执行语句至少执行一次。
在图例中,正好所有的可执行语句都在路径L1上,所以选择路径L1设计测试用例,就可以覆盖所有的可执行语句。
测试用例的设计格式如下:【输入的(A, B, X),输出的(A, B, X)】为图例设计满足语句覆盖的测试用例是:【(2, 0, 4),(2, 0, 3)】覆盖 ace 【L1】1.3.3 判定覆盖判定覆盖:判定覆盖又称为分支覆盖。
就是设计若干个测试用例,运行被测程序,使得程序中每个判断的取真分支和取假分支至少经历一次。
对于图例,如果选择路径L1和L2,就可得满足要求的测试用例:【(2, 0, 4),(2, 0, 3)】覆盖 ace 【L1】【(1, 1, 1),(1, 1, 1)】覆盖 abd 【L2】如果选择路径L3和L4,还可得另一组可用的测试用例:【(2, 1, 1),(2, 1, 2)】覆盖 abe 【L3】【(3, 0, 3),(3, 0, 1)】覆盖 acd 【L4】()()()()()A XB A X ≤≤≠≠≤11021and or and and1.3.4 条件覆盖条件覆盖:条件覆盖就是设计若干个测试用例,运行被测程序,使得程序中每个判断的每个条件的可能取值至少执行一次。
在图例中,我们事先可对所有条件的取值加以标记。
例如,对于第一个判断:条件 A >1 取真为 ,取假为 ;条件 B =0 取真为 ,取假为 。
对于第二个判断:条件A =2 取真为 ,取假为 ;条件X >1 取真为 ,取假为 。
测试用例 覆盖分支 条件取值【(2, 0, 4),(2, 0, 3)】 L1(c, e)【(1, 0, 1),(1, 0, 1)】 L2(b, d) 【(2, 1, 1),(2, 1, 2)】 L3(b, e)或测 试 用 例 覆盖分支 条件取值【(1, 0, 3),(1, 0, 4)】 L3(b, e)【(2, 1, 1),(2, 1, 2)】 L3(b, e)1.3.5 判定-条件覆盖判定-条件覆盖:判定-条件覆盖就是设计足够的测试用例,使得判断中每个条件的所有可能取值至少执行一次,同时每个判断中的所有可能取值至少执行一次。
例如:测试用例 覆盖分支 条件取值【(2, 0, 4),(2, 0, 3)】 L1(c, e)【(1, 1, 1),(1, 1, 1)】 L2(b, d)(A=2)and (B=0)or (A>1)and (B=0)and (X/A>1);(A ≤1)and (X ≤1)or (B ≠0)and (A ≠2)and (X ≤1)4321TT T T 4321T T T T 4321T T T T 4321T T T T 4321T T T T 4321T T T T 1T 1T 2T 2T 3T 3T 4T 4T 4321T T T T1.3.6 条件组合覆盖条件组合覆盖:条件组合覆盖就是设计足够的测试用例,运行被测程序,使得每个判断的所有可能的条件取值组合至少执行一次。
例: ① A >1, B =0 作② A >1, B≠0 作③ A ≯1, B =0 作④ A ≯1, B≠0 作⑤ A =2, X >1 作⑥ A =2, X ≯1 作 ⑦ A≠2, X >1 作⑧ A≠2, X ≯1 作 测 试 用 例 覆盖条件 覆盖组合【(2, 0, 4), (2, 0, 3)】 (L1) ①, ⑤ 【(2, 1, 1), (2, 1, 2)】 (L3)4321T T T T ②, ⑥【(1, 0, 3), (1, 0, 4)】 (L3)4321T T T T ③, ⑦【(1, 1, 1), (1, 1, 1)】 (L2)4321T T T T ④, ⑧1.3.7 路径覆盖路径覆盖:路径测试就是设计足够的测试用例,覆盖程序中所有可能的路径。
测 试 用 例 通过路径 覆盖条件【(2, 0, 4), (2, 0, 3)】 ace (L1) 4321T T T T【(1, 1, 1), (1, 1, 1)】 abd (L2) 4321T T T T【(1, 1, 2), (1, 1, 3)】 abe (L3) 4321T T T T【(3, 0, 3), (3, 0, 1)】 acd (L4) 4321T T T T21T T 21T T 21T T 21T T 43T T 43T T 43TT 43T T 4321T T T T1.4循环测试循环测试主要关注循环体结构的正确性,对循环变量运用类似于边界值测试的方法以验证循环体结构的正确性。
循环测试主要由四种不同类型的循环结构简单循环;嵌套循环;连接循环;非结构循环1.4.1简单循环如果n 是循环次数, 那么测试用例应包括➢直接跳过循环体;➢只执行一遍循环体;➢连续执行两遍循环体;➢如果循环次数为n,执行m(m < n)遍循环体;➢如果循环次数为n,那么执行n -1遍循环体;➢如果循环次数为n,那么执行n遍循环体;➢如果循环次数为n,那么执行n + 1遍循环体。
Beizer’s 的方法:➢从最内层测试开始,其它层的循环变量置为最小值➢按照简单循环的测试方法测试最内层的循环体,外层循环仍旧取最小值➢向外扩展循环体,测试下一个循环1.所有外层循环变量取最小值;2.其余内层嵌套的循环体取典型值;3.继续本步骤直到所有的循环体均测试完毕。
1.4.3连接循环➢如果相连接的循环体互相独立,按照简单循环测试每一个循环体;➢如果相连接的循环体1的循环变量的最终结果是循环体2循环变量的初始值,那么采用嵌套循环的方法来测试(靠前认为是内层循环)。
➢测试非结构循环是一件令人头痛的事情➢最好的方法是重新设计循环体结构1.5程序插桩程序插装是一种基本的测试手段。
它是在程序特定部位插入“探针”,以便把程序执行过程中发生的一些重要历史事件记录下来(如语句执行次数、某些变量值的变化情况等),只有借助于插装技术,才能了解程序执行时的语句覆盖、分支覆盖及路径覆盖等结构覆盖情况。
在被测程序中插入的操作(语句)称为“探测器”或“探针”。
例如:求取两个整数X和Y的最大公约数程序如下:int gsd (int X, int Y){ int Q=X;int R=Y;while(Q!=R){ if(Q>R)Q=Q-R;else R=R-Q;}return Q;}为了记录改程序中语句的执行次数,我们使用插桩技术插入如下语句:C(i)=C(i)+1,i=1,2, (6)插桩之后的流程图如下:在程序入口处插入对计数器C(i)的初始化语句在程序出口处加入打印语句图中虚线框中的内容并不是源程序的内容,而是我们为了记录语句的执行次数而插入的。
虚线框中的程序就是为了完成计数。
形式就是C(n)=C(n)+1 ; n = 1,2,3,……,n ;该程序从入口开始,到出口执行结束。
凡经历的计数语句都能记录下该程序点的执行次数。
如果我们在程序的入口处还插入了对计数器C(i)初始化的语句,在出口处插入了打印这些计数器的语句,就构成了完整的插桩程序。
它就能记录并输出在各程序点上语句的实际执行次数。
下图为插桩之后的程序,箭头所指为插入的语句。
源程序的语句已略去。
设计插桩程序时需要考虑的问题包括:(1)探测哪些信息。
这个问题需要具体问题具体分析。
(2)在程序的什么部位设置探测点。