白盒测试又称为覆盖率测试
首先介绍覆盖率的概念
覆盖率是用来度量测试完整性的一个手段,大体上可以分为两大类:点覆盖和边覆盖
覆盖率=被执行的item数/item的总数*100%
通过覆盖率数据,可以知道测试工作做得是否充分,测试的弱点在哪些方面,进而指导人们设计能够增强覆盖率的测试用例
白盒测试要求测试人员对程序的逻辑结构有清楚的了解,甚至要求掌握代码的细节
(1)逻辑覆盖测试
逻辑覆盖方法又可分为语句覆盖,块覆盖,判断覆盖,判定-条件覆盖,条件组合覆盖以及路径覆盖
通过一个简单的函数为例子来分别对各个覆盖方法做出简要介绍
程序如下:
public int Test(int A,int B,int X) { if(A>1&&B==0) { X=X/A; } if(A==2||X>1) { X=X+1; } return X; }
函数流程图如下:
通过流程图可以得到
该函数有四条不同的路径,分别对第一个判定的取假分支,取真分支以及第二个判定的取假分支,去真分支命名为b,c,d,e
所以四条路径可以表示为:
p1(a->c->e)
p2(a->b->d)
p3(a->b->e)
p4(a->c->d)
1.语句覆盖与块覆盖
所谓的语句覆盖就是设计若干测试用例,运行被测试程序,使得每一个可执行语句至少执行一次,若干个是指测试用例越少越好
语句覆盖率=被评价到的语句数/可执行的语句数*100%
在本例中,所有可执行的语句刚好在p1这条路径上(注意,所有可执行的语句和所有可执行的流程并不相等,本例所有可能的流程为p1,p2,p3,p4)
所以针对p1设计测试用例
满足语句覆盖率可以达到100%的测试用例可以是:
Test1:[(2,0,4),(2,0,3)] 覆盖路径ace[p1]
从度量的角度看,语句覆盖方法设计的测试用例始终跟踪 可执行的语句 的执行情况
对代码达到100%的语句覆盖率也是现实的
然后语句覆盖方法发现缺陷的能力很弱,不能发现程序中出现的一些逻辑错误,所以语句覆盖是 最弱 的逻辑覆盖准则
块覆盖是语句覆盖的一个变体,唯一的区别就是计算方式不同
指令块是函数体中的一组语句,在这组语句中不存在控制语句(会引起分支的)
块覆盖率=被执行的块数/总块数*100%
2.判定覆盖
判定覆盖是使得程序中每个判定的取真取假分支至少被评价一次,所以又被称为分支覆盖
判定覆盖率=被评价到的分支数/总分支数*100%
对于本例函数,相对于选择路径12和路径34
可以满足的测试用例各有不同
所以测试用例的取法不唯一
但是判定覆盖也没有办法发现程序中的一些逻辑错误
判定路径覆盖
由于并不是所有的判定条件都是两分支的,如Switch,以及判定条件可能出现很复杂的情况
所以使用简单的判定覆盖极易出现漏判情形,所以就出现了变体---判定路径覆盖
它将每一个判定语句序列当做一条路径,该路径的起始位置是一个判定的入口(如if,switch等),终点位置是另外一个判定的入口
3.条件覆盖
条件覆盖率=被评价到的条件取值的数量/条件取值的总数*100%
从公式中可以看出条件覆盖的特点,就是取判定中条件的所有取值可能进行测试
这样看来,条件覆盖似乎和判定覆盖有着共同点
可是事实上满足了条件覆盖的测试用例并不一定可以满足判定覆盖
4.条件--判定覆盖
为了解决条件覆盖和判定覆盖的矛盾,就可以考虑使用条件---判定覆盖
条件--判定覆盖率=条件覆盖率/判定覆盖率=被评价到的条件取值数+被 评价到的分支数量/条件取值总数+判定分支总数
所以,根据公式卡可以知道,条件--判定覆盖就是设计足够的测试用例,使得函数中的每一个判定条件的取值至少被评价一次同时所有的判定分支至少被评价一次
5.条件组合覆盖
条件组合覆盖率=被评价的条件组合数/总条件组合数
条件组合就是每个判定的所有可能取值的组合,如例子函数中的(1)(a>1&&b==0)(2)(a>1&&b!=0)
这就是两个不同的条件组合,在本例函数中有8个条件组合,进行条件组合覆盖时要先给出所有的可能的条件组合
然后根据这些条件组合设计测试用例进行测试
6.路径覆盖
路径覆盖率=被评价到的路径数/程序中的路径总数
7.逻辑覆盖总结
尽管从语句覆盖到路径覆盖,发现程序中的逻辑错误能力已经逐步加强,但是仍然不可避免的无法检查出程序中的一些逻辑错误
数据表名,最容易出错的部分是判定条件中的条件表达式
所以为了更好的解决这个问题,出现了ESTCA和LCSAJ覆盖的概念
(2)路径测试
1.分支结构的路径测试
由于程序中存在中而大量的分支结构,所以要做到100%的路径测试是比较不可能实现的
所以可是使用正交实验设计法抽取部分路径进行测试
当程序中的路径重要性都一样或者不明白程序中路径的重要性的时候可以使用随机均匀抽样
反之,可使用加权的方法抽取部分路径
具体步骤为:
1)假设分支结构中有n个判断语句,n+1<=2的m次方 计算满足该关系式的最小自然数m
2)设t=2的m次方 去正交表Lt,并利用它设计测试数据
2.循环结构的路径测试
对于简单循环,测试应包括一下几种:
0次循环:从循环入口直接跳转到循环出口
1次循环:查找在循环初始值方面的错误
m次循环:m<n,检查多次循环下可能出现的错误
最大次数循环,最大次数少一次的循环,最大次数多一次的循环
如果将简单循环的测试扩大到嵌套循环,可能导致一个天文数字的测试数目,所以应该使用如下的测试方法进行适当的选择:
测试最内层循环,其他外层的循环次数置为1
逐步外推,测试该层循环,其他层的循环置为1
测试最外层的循环,其他内层的循环置为1
(使用简单循环的测试方法对相应的循环进行测试)
3.圈复杂度与基本路径测试
(3)数据流测试
数据流测试也可是看做是一种路径测试,它主要关注在一条路径上变量是在何处定义,何处使用的,通过监视变量的定义和使用异常来分析源代码
第一类定义/使用异常:变量被定义,但从未被使用
第二类定义/使用异常:所使用的变量从未被定义
第三类定义/使用异常:变量在使用之前重复被定义
(4)基于覆盖的测试用例选择
在使用逻辑覆盖的测试时,选择和使用覆盖率必须基于以下几个原则:
1)覆盖率不是目的,只是一种手段。
2)不可能针对所有的覆盖率指标进行测试,反之,只进行一种覆盖率的测试要是不可取的
3)不要追求觉得100%的覆盖率
(5)程序插桩技术
程序插桩要成为程序插装,其含义就是通过向北侧程序源代码中插入特定的代码来查看程序的状态,寻找缺陷
如,经常需要在测试程序的时候在特定的地方插入一些打印语句
程序插桩的基本思想和步骤为:
1)插入探针(如打印语句等)
2)编译执行并输出探针数据(挑选测试用例)
3)处理探针执行的特殊数据