目录
一、什么是白盒测试
在了解白盒测试之前,首先回顾一下黑盒测试的常用方法:
【软件测试篇5】如何设计测试用例_测试开发设计测试用例_革凡成圣211的博客-优快云博客在前面的文章当中,也提到了什么是测试用例。测试用例就是测试人员向被测试系统提供的一组测试数据。包括:测试环境、测试步骤、测试数据、预期结果。那么,下面将来聊一聊,具体怎样设计测试用例。_测试开发设计测试用例https://blog.youkuaiyun.com/weixin_56738054/article/details/129667293?spm=1001.2014.3001.5501 其实无论是白盒测试还是黑盒测试,都是通过模拟输入、输出来判断是否符合预期。但是白盒测试与黑盒测试不一样的地方就是,黑盒测试只关注业务需求上面的实现。 白盒测试需要关注内部的代码逻辑,也就是根据代码逻辑来设计测试用例。
白盒测试的特点
优点
白盒测试的优点就是代码覆盖率比较高,可以覆盖到所有的if,else,where语句等等的分支。
缺点
①覆盖所有路径的难度比较大
例如:当一个if语句下面有多个if,where嵌套的时候,如果要覆盖到所有的分支,那么就要设计多个case的组合才可以实现;
②业务功能可能覆盖不全
一个业务功能可能需要多条语句分支的实现,但是往往白盒测试不一定能覆盖全,甚至很可能会覆盖漏掉。
③测试开销比较大
如果想依赖白盒测试覆盖掉项目的整个路径,完整测试出所有的功能,那么白盒测试的代码未必比开发的代码量小。
黑盒测试和白盒测试的配合使用
白盒测试往往是跟黑盒测试不分家的。对于一些比较简单的业务场景,我们通常直接采用黑盒测试即可。但是对于一些比较复杂的业务场景,也就是内部代码比较复杂的逻辑,我们就往往需要白盒测试来一起进行测试。
二、白盒测试设计方法
①静态
在这一部分,也就是我们常说的code review。
通常我们需要检查一下有没有明显的代码逻辑上面的错误,例如可能出现空指针异常、数组越界,或者方法返回值错误等等的比较明显的错误。
下面罗列一部分常见的在code review部分遇到的代码错误:
①参数少传递了;
②数组索引越界;
③空指针异常:未初始化直接使用;
④边界行为错误:例如int c=a/b,那么是否考虑b=0的情况;
⑤经验错误:例如if(a==3)的判定条件写成了if(a=3);
⑥算法错误:例如当且仅当用户签到满7天的时候会下发一个奖励,但是实际上签到满了并没有下发。
②动态
行覆盖(语句覆盖):度量该代码行是否被测试到,这里要求最低的覆盖率标准。也就是这一行代码是否被覆盖到。
判定覆盖(分支覆盖):度量程序当中每个判定的分支是否被测试到。例如:if,sles,where等等。
条件覆盖:度量判定中的每个条件的取值至少满足一次。
逻辑覆盖法
是通过对程序逻辑结构的遍历实现程序的覆盖。也就是当程序运行起来的时候,需要走到每一个item上面。此处的item指的是语句、判定、条件、判定条件、组合条件、路径。
覆盖率=至少被执行一次的item数/item的总数
例如:案例代码当中共有4条可执行语句,设计测试用例执行了3条,语句覆盖率为3/4=0.75
代码的覆盖率需要尽可能高。
行覆盖(语句覆盖)
其实就是度量每一行代码是否被覆盖到。
看下面这一段代码:
static int logicExample(int x,int y,int magic){
int a;
if(x>0&&y>0){
//语句块1
a=x+y+10;
}else {
//语句块2
a=x+y-10;
}
if(magic<0){
//语句块3
a=0;
}
//语句块4
return a;
}
如果想实现语句覆盖达到100%,也就是:
覆盖到:语句块1+语句块3+2。那么如下两组输入就可以实现:
{x=3,y=1,magic=2}:覆盖到了语句块1
{x=-3,y=-1,magic=-2}:覆盖到了语句块2+语句块3.
那么也就实现了100%的覆盖率。
语句覆盖的局限性
对于if判定的条件,无法每一个都覆盖到。例如上述的例子当中,x>0&&y>0,输入示例只有x=3&&y=1,但是无法令每一个判定都被组合一遍。因此也就需要引入判定覆盖
判定覆盖(分支覆盖)
也叫分支覆盖,设计测试用例使得程序当中的每个判断的”真“和”假“都被至少执行1次。
判定覆盖率=每个判定的真假值至少出现1次/判定结果的总数。
例如针对if(m>0&&n>0)做行覆盖的时候,只需要执行的代码覆盖到这一条语句就行。
做判定覆盖的时候,需要取:
m>0为true和false各一次。
n>0为true和false各一次。
条件覆盖
在情况允许的情况下面,如果遇到了多个if语句嵌套的情况,就需要用到条件覆盖。
例如:
class Solution{
public static void main(String[] args) {
int a=3,b=4,c=5;
System.out.println(get(a,b,c));
}
public static int get(int a,int b,int c){
//第一层if语句
if(a==0&&b==1){
//第二层if语句
if(c==5){
return 0;
}
}
return 1;
}
}
对于上面这一段代码,发现了两个if语句相互嵌套的情况,如果要做到条件覆盖,那么就需要一共设计:(2+2)*2=8个用例。
即:
第一层if语句:真(a==0)真(b==1)、真(a==0)假(b!=1)、假(a!=0)真(b==1)、假(a!=0)假(b!=1)。
第二层if语句:真(c==5)、假(c!=5);
二者组合一下:就是:
真真真、真真假、真假真、真假假、假真真、假真假、假假真、假假假。
一共2的平方乘以2的平方乘以2的1次方=8个用例。
条件覆盖2
class Solution{
public static void main(String[] args) {
int a=3,b=4,c=5;
System.out.println(get(a,b,c));
}
public static int get(int a,int b,int c){
//第一层if语句
if(a==0&&b==1){
return 2;
}
//第二层if语句
if(c==5){
return 0;
}
return 1;
}
}
在上述的例子当中:
第一个if语句,有两个条件,因此就是:2+2=4,一共4个用例。
在第二个if语句当中,2.
因此一共需要4+2=6个用例。