1、基于结构的动态测试主要关注语句、分支、路径、调用等程序结构的覆盖,为了设计较少的用例,达到更高的覆盖率甚至100%的覆盖率,动态测试关键的是用例设计。
2、基于结构的动态测试用例设计,设计基础建立在对程序的控制结构的了解上。原则上应做到:
保证一个模块中的所有独立路径至少被使用一次;
对所有逻辑值均需测试true和false;
在上下边界及可操作范围内运行所有循环;
检查内部数据结构以确保其有效性。
3、基于结构的动态测试用例设计方式可分为基于控制流和数据流两大类。
基于控制流设计用例
基于控制流设计用例,是通过对程序控制流所表达出来的逻辑结构的遍历,实现对程序不同程度的覆盖。
基于结构的测试中编写测试用例要经历特征集—>测试条件—>测试覆盖项—>测试用例这样一个过程,其中基于控制流设计的用例里,测试特征集都是被测的代码段,不同的用例设计方法体现在测试条件和测试覆盖项的不同上,导致后续测试用例的不同。
测试用例的覆盖率指的是执行对应测试用例所覆盖到的测试覆盖项个数占全部测试覆盖项的百分比。
下面,通过举例来演示上述不同测试覆盖标准 所对应的测试设计:
(1)语句测试——选择足够多的测试数据,使被测程序中每条语句都要被遍历到。
语句覆盖对程序执行逻辑的覆盖很低。
为使实例中每条语句都能够至少执行一次,可构造测试用例:输入a=T,b=T,c=T,预期结果x=1。但上图中右侧的代码分支没有语句,所以覆盖完全部语句时可能验证不到程序某个分支。
(2)分支测试——使程序中每个分支都被遍历到,即使该分支上没有语句。
示例中有两个分支,每个分支对应一个测试覆盖项。可以看出,当分支覆盖率达到100%时,语句覆盖率必然也达到100%,分支覆盖比语句覆盖要更强一些。但假如示例中判定的逻辑运算有问题(第一个运算符&&错写成||)时,使用上述测试用例仍然可以达到100%的分支覆盖,导致代码中该逻辑错误无法被发现,因此还需要更强的逻辑覆盖标准。
(3)判定测试——使程序中的每个判定语句的取值都要被遍历到。对于真假双值的判定,应设计测试用例使判定语句至少取“真”值和取“假”值各一次;对于多值判定,如switch-case结构,设计测试用例保证所有case和default分支均要取到。
由于程序中的不同分支都是基于判定语句的取值划分的,判定测试和分支测试密切相关。当达到判定测试100%覆盖时,所选的测试用例也达到分支测试100%覆盖,而达到分支测试100%覆盖时,所选的测试用例也达到判定测试100%覆盖,二者经常被混为一谈。
但是,在计算具体某个测试用例或用例集的覆盖率时,当覆盖率不为100%,判定覆盖率和分支覆盖率的值就并不完全一致了。
(4)分支条件测试——设计足够的测试用例,使得每个判定语句的取值,以及每个判定条件的取值都能被覆盖到。
示例中为复合判定语句,包含三个判定条件:a,b,c。基于分支或判定语句的覆盖无法测试到复合判定中的各个判定条件。因此,产生了条件覆盖,即针对覆盖所有的判定条件的要求设计测试用例,使程序中每一条判定语句中每个判定条件的可能值至少满足一次。
但是,覆盖了100%的判定条件时可能存在有的分支没有覆盖到,因此单纯使用条件覆盖是不够的,需要与分支结合起来一起考虑,即分支条件测试。
分支条件测试也存在强度不够的缺陷,假如 示例中判定的逻辑运算有问题(判定语句错写成a||(b%%c))时,使用上述测试用例仍然可以达到100%的分支条件覆盖,导致代码中该逻辑错误无法被发现,因此还需要更强的逻辑覆盖标准。
(5)分支条件组合测试——设计足够的测试用例,使每个判定语句中的所有判定条件的各种可能组合都至少出现一次。
满足分支条件组合测试100%覆盖的用例集,其语句测试、分支测试、判定测试、分支条件测试的覆盖率也一定是100%。
对于包含n个布尔条件的代码,需要个测试用例来实现100%的覆盖。
示例中设计的测试用例应该满足a,b,c取这些值(1表示T,0表示F):0 0 0, 0 0 1, 0 1 0,0 1 1, 1 0 0, 1 0 1, 1 1 0, 1 1 1,共8组取值。
(6)修正条件判定测试(MCDC)——要求足够的测试用例来确定各个条件能够影响到包含的判定的结果。
修正条件判定测试(MCDC)方法既保持了与分支条件组合测试相同的覆盖强度,又显著减少了需要的测试用例。
修正条件判定测试(MCDC)要满足两个条件,首先,每一个程序模块的入口和出口点都要考虑至少被调用一次,每个程序的判定到所有可能的结果值至少转换一次,其次,程序的判定被分解为通过逻辑操作符连接的bool条件,每个条件对于判定的结果值都是独立的。