单元测试用例基础设计思想总结
by:授客QQ:1033553122
基于网络相关资料,加上个人理解,总结的单元测试用例设计思想。
语句覆盖
要求设计足够多的测试用例,使得函数中的每条语句都至少执行一次。
例子
对应代码:
// 语句覆盖
public intfunc1(intx) {
inta =0;
if(x <0) {
a = a +1;
}
returna;
}
用例设计
x = -1
注:简单的说,用例大致由3部分组成,一部分是操作,一部分是操作时使用的测试数据,另一部分是输出及预期结果等,这里操作和输出预期结果等都暂且不提,这里说的用例设计,主要是指设计测试数据,因为这个是核心,下同,不再赘述
缺点分析
语句覆盖不考虑判断条件,容易导致漏测,如上,虽然执行了每条语句(int a = 0; a = a + 1; return a;),但是因为没考虑条件if (x < 0),导致x >= 0的情况未被测到。
判定覆盖
也称为“分支覆盖”,要求设计足够多的测试用例,使得函数中的每个判断的的每条分支都必须至少执行一次。
例子
对应代码
public voidfunc2(inty) {
if(y ==0) {
y = y +1;
}else{
y = y +2;
}
}
public voidfunc3(inti) {
switch(i) {
case 1: i = i +1;break;
case 2: i = i +2;break;
case 3: i = i +3;break;
}
}
用例设计
y = 0
y = 1
i = 1
i = 2
i = 3
对应代码
public intfunc4(intx, inty){
inta;
if(x <2) {
x = x +1;
}
if(y >3) {
y = y +3;
}
a = x + y;
returna;
}
用例设计
x = 1, y = 2
x = 3, y = 4
代码:
public intfunc5(inta, intb) {
if(a <1&& b >5) {
returna - b;
}else{
returna + b;
}
}
用例设计
a = 0
a = 2
缺点分析
1、判定覆盖只考虑了判断的每条分支,但是未考虑所有判断的分支组合,如上,绿色线条所代表的路径(第一个判定结果为false,第二个判定结果为true的情况)就未测到
2、判定覆盖只考虑了判断的最终结果,未考虑判断中每个条件的取值情况,这容易导致业务逻辑漏测,如上最后一个例子,假设a < 1 && b > 5应该写成a < 1 || b > 5,按上述用例也无法发现这个问题
条件覆盖
要求设计足够多的测试用例,为函数中每个判断中的每个条件表达式的设计了所有可能结果值。
例子
对应代码:
public intfunc5(inta, intb) {
if(a <1&& b >5) {
returna - b;
}else{
returna + b;
}
}
用例设计
a = 0(条件表达式a<1为true),b = 4(条件表达式b>5为false)
a = 2(条件表达式a<1为false), b = 6(条件表达式b>5为true)
缺点分析
1、同判定覆盖,条件覆盖只考虑了判断里的条件表达式,未考虑每个判断的结果分支组合,会导致漏测
2、条件覆盖更关注判断中每个条件的取值覆盖,未考虑判断中所有条件的取值结果组合(整个判断的结果会受到条件表达式之间的 && 、||等逻辑关系影响),这容易导致漏测,如上,虽然每个条件表达式都设计了可能值,但是return a - b 仍未执行到。
3、未考虑判断中所有条件的取值结果组合,这容易导致业务逻辑漏测
判定/条件覆盖
要求设计足够多的测试用例,使得函数中的每个判断的每条分支都必须至少执行一次,且用例为每个判断中的每个条件表达式的设计了所有可能结果值。
例子
public intfunc5(inta, intb) {
if(a <1&& b >5) {
returna - b;
}else{
returna + b;
}
}
a = 0(条件表达式a<1为true),b=6 (条件表达式b>5为true) 判断结果为true
a = 1(条件表达式a<1为false), b=5(条件表达式b>5为false)判断结果为false
缺点分析
1、同条件覆盖,只考虑了判断里的条件表达式,未考虑每个判断的结果分支组合,会导致漏测
2、同条件覆盖,关注判断中每个条件的取值覆盖,未考虑判断中所有条件的取值结果组合(整个判断的结果会受到条件表达式之间的 && 、||等逻辑关系影响),这容易导致业务逻辑上的漏测,比如上述条件 a < 1 && b > 5本应该是 a < 1|| b > 5,按上述测试数据,也无法发现这个错误。
条件组合覆盖
要求设计足够多的测试用例,为每个判断中的所有“条件表达式的可能结果”的“组合结果”设计了所有可能值。
例子
对应代码:
public intfunc5(inta, intb) {
if(a <1&& b >5) {
returna - b;
}else{
returna + b;
}
}
用例设计
a = 0(条件表达式a<1为true),b=6 (条件表达式b>5为true)
a = 0(条件表达式a<1为true), b=5(条件表达式b>5为false)
a = 1(条件表达式a<1为false), b=5(条件表达式b>5为false)
a = 1(条件表达式a<1为false), b=6(条件表达式b>5为true)
缺点分析
同条件覆盖,只考虑了单个判断,未考虑函数中所有判断的结果分支组合,会导致漏测
路径覆盖
顾名思意,覆盖函数中的每一条路径,也可以简单理解为所有判断条件的分支组合
例子
对应代码:
// 前一个判定的一个、多个分支路径中变量取值结果影响后续判定中的变量取值
// (前提:前一个判定分支路径的执行不会结束函数的执行,判定与判定直接处于同一层级,即为“同胞”关系,非嵌套包含,形如以下则为嵌套包含关系
// if (express1) { if (express2) {}}下同
public intfunc6(intx, inty){
intz =0;
inta =0;
if(x <2) {
z = z +1;
}
if(y >3) {
a = z +2;
}
returna;
}
// 前一个判定的一个、多个分支路径中变量取值结果影响后续判定中的判定取值
public intfunc7(intx, inty){
intz =0;
inta =0;
if(x <2) {
z = z +1;
}
if(y >3) {
if(z !=0) {
a =10;
}
}
returna;
}
// 不同判定的一个、多个分支路径中变量取值结果影响后续非判定分支路径中的语句的结果取值
public intfunc8(intx, inty){
inta;
if(x <2) {
x = x +1;
}
if(y >3) {
y = y +3;
}
a = x + y;
returna;
}
}
用例设计
(以第一个函数为例子)
x = 1 (x<2 true), y=4 (y>3为true)
x = 1 (x<2 true), y=3 (y>3为false)
x = 2 (x<2 false), y=4 (y>3为true)
x = 2 (x<2 false), y=3 (y>3为false)
缺点分析
1、路径复杂的情况下,用例数可能太多,无法实现
2、同判定覆盖,只考虑了判断的最终结果,未考虑判断中每个条件的取值情况,这容易导致业务逻辑上的漏测
最终总结
1、无特殊情况下,使用条件组合覆盖(不对判断的路径做组合覆盖,只提供必要路径,即走完前一个判断,能走到下一个判断; 当然,这里的所说的条件组合覆盖是默认包含了语句覆盖),测试时结合实际业务逻辑检查相关判断表达式是否正确
2、当函数中存在多个判断条件,存在以下几种情况之一的,条件覆盖的基础上,可以根据实际情况补充路径覆盖(暂时只想到这些)
Ø 前一个判段的一个、多个分支路径中变量取值结果影响后续判定中的变量取值
Ø 前一个判段的一个、多个分支路径中变量取值结果影响后续判定中的判定取值
Ø 不同判段的一个、多个分支路径中变量取值结果影响后续非判定分支路径中的语句的结果取值
路径深度:同一层级相关判断的分支
纳入路径覆盖范围的判断:正如上述说的影响“取值”的那些判断
3、在上述基础上,适当结合等价类划分,边界值等用例设计方法,适当补充、修改用例,特别注意入口参数,结合业务考虑是否存在“隐式”的条件