6种白盒测试
实例比较6种白盒测试
语句覆盖
判定覆盖或分支覆盖
条件覆盖
判定/条件覆盖
多重条件覆盖
路径覆盖
MK2方法:
强烈推荐:多重条件覆盖
如果程序模块中没有循环,可以考虑路径覆盖
例子: public void foo(int a, int b, int x) {
if (a > 1 && b == 0) {
x = x / a;
}
if (a == 2 || x > 1) {
x = x + 1;
}
}
1.语句覆盖
语句覆盖:语句覆盖是最起码的结构覆盖要求,语句覆盖要求设计足够多的测试用例,使得程序中每条语句至少被执行一次。
测试用例
测试对应:a=2,b=0,x=3,每条语句被执行一次
不足
遗憾的是,这个准备相当不足。举例来说,也许第一个判断a > 1 && b == 0 应是“或”,而不是“与”。如果是这样,错误就会发现不到。另外可能第二个判断应该写成x > 0,这个错误也不会被发现。还有,程序中存在一条x未发生改变的路径(路径ABD),如果这是个错误,它也不会被发现。
结论
语句覆盖这个准则有很大的不足,以至于它通常没有什么用处。由于这种测试方法仅仅针对程序逻辑中显式存在的语句,但对于隐藏的条件和可能到达的隐式逻辑分支,是无法测试的。
2.判定覆盖或分支覆盖
判定覆盖又称为分支覆盖,它要求设计足够多的测试用例,使得程序中每个判定的每个可能结果(true、false)都至少执行一次,以及将程序或者子程序的每个入口点都至少执行一次。
测试用例
两个覆盖路径:路径ACE,路径ABD,或者覆盖了ACD和ABE的测试用例就满足了判定覆盖的要求
不足
仍然相当的不足。举例来说,我们仅有50%的可能性遍历到那条x未发生变化的路径(也即,我们选择前一种情况)。如果第二个判断存在错误(如把x > 1 写成了x < 1),那么前面两个例子中的两个测试用例都无法找出这个错误。
结论
往往大部分的判定语句是由多个逻辑条件组合而成,若仅仅判断其整个最终结果,而忽略每个条件的取值情况,必然会遗漏部分测试路径。
3.条件覆盖
条件覆盖要求设计足够多的测试用例,使得判定中的每个条件获得各种可能的结果,即每个条件至少有一次为真值,有一次为假值。
测试用例
例子中4个条件:a > 1 , b == 0,a == 2, x > 1。因此需要足够的测试用例,使得在A处出现a > 1、a <= 1、b == 0、b != 0,在点B处出现a == 2、a != 2、x > 1、x <= 1的情况。选择用例1.a=2, b=0, x=4 路径ACE;2.a=1, b=1, x=1 路径ABD
不足
条件覆盖并不能保证判定覆盖。举例来说:1.a=1, b=0, x=3 ABE 2.a=2, b=1, x=1 ABE,满足条件覆盖,却不满足判定覆盖
结论
有的分支只执行true和false中的一个,条件覆盖并不能保证判定覆盖
4.判定/条件覆盖
设计足够多的测试用例,使得判定中每个条件的所有可能结果至少出现一次,每个判定本身所有可能结果也至少出现一次。
测试用例
判定 if (a > 1 && b == 0) 和 if (a == 2 || x > 1) 都至少取一次true和false,使条件a > 1 、 b == 0、a == 2、 x > 1都至少取一次true和false
不足
判定/条件覆盖准则的缺点是未考虑条件的组合情况;并且,不一定会发现逻辑表达式中的错误
结论
判定/条件覆盖满足判定覆盖准则和条件覆盖准则,弥补了二者的不足。
5.多重条件覆盖
又名组合覆盖,要求设计足够多的测试用例,使得每个判定中所有可能的条件结果组合,以及所有的入口点都至少执行一次
测试用例
对于判定 if (a > 1 && b == 0) 和 if (a == 2 || x > 1) ,需要使条件a > 1 、 b == 0都至少取一次true和false,然后进行组合;a == 2、 x > 1都至少取一次true和false,再组合
不足
线性地增加了测试用例的数量
结论
多重条件覆盖准则满足判定覆盖、条件覆盖和判定/条件覆盖准则。强烈推荐
|
设计 |
步骤1 |
列出判定清单 |
|
1. if (a > 1 && b == 0) |
步骤2 |
列出判定中的条件清单 |
|
判定1: 1.a > 1 2. b == 0 |
步骤3 |
列出每个条件的可能结果清单 |
|
1.a > 1
, a <= 1 |
步骤4 |
每个判定中所有可能的条件结果组合至少出现一次 |
|
判定1的可能结果组合 |
步骤5 |
设计足够测试用例,覆盖所有可能的条件结果组合至少一次 |
|
a=2, b=0,
x=4 覆盖组合1,5 |
6.路径覆盖
设计足够的测试用例,覆盖程序中所有可能的路径。
不足
时间成本,如果遇到循环,测试时间和测试成本……消耗太多
结论
时间成本太高;不推荐。如果程序分支比较少,循环没有或者很简单,才使用
7.异常系的测试
源代码
try { InsSecurity.getNavigwareUserInstance(userId); } catch (CnCAccountLockOutException e) { context.put("popup", Boolean.TRUE); throw new InsCommandException( InsPortalWebUIErrors.ERROR_USER_LOCKEDOUT); } catch (Exception e) { }
|
异常
已知getNavigwareUserInstance要抛出3个异常,所以请测试这3个异常 public static InsUser getNavigwareUserInstance(String userId) throws CnCUnknownEntityException, CnCAccountLockOutException, DataBackendException {
|
测试方法:在代码中加入异常语句,测试异常;每条catch路径必须测到
例如:测试CnCAccountLockOutException try { InsSecurity.getNavigwareUserInstance(userId); if(true){ throw new CnCAccountLockOutException(); } } catch (CnCAccountLockOutException e) { context.put("popup", Boolean.TRUE); throw new InsCommandException( InsPortalWebUIErrors.ERROR_USER_LOCKEDOUT); } catch (Exception e) { } |
请发表评论