首页 » C语言解惑 » C语言解惑全文在线阅读

《C语言解惑》13.10 测试用例设计技术

关灯直达底部

既然无法对软件进行彻底的测试,那么测试用例的设计便是测试是否取得成功的根本保证。为此,测试人员必须采用那些能够以尽量少的测试数据来发现尽量多的错误的测试技术。

不同的测试在选择测试用例方面有着很大差别。白盒测试法是根据详细设计中的逻辑流程来设计测试用例,以暴露编码中的逻辑错误,如是否存在不可执行的路径或无限循环等。属于这类测试法的有逻辑覆盖法。黑盒测试是用“软件需求说明书”来设计测试用例,即把软件看成黑盒子,对输入进行转换,检查输出的正确性。属于这类测试法的有等价划分法、边值分析法、错误猜测法等。这些测试用例设计技术各有优缺点,没有哪一种是最好的,更没有一种技术能够代替其他所有技术。同一种技术对不同的应用问题,其效果也可能相差很大。因此,对于软件测试,通常需要联合使用多种测试用例设计方法,才能发现软件的各种各样的错误。

13.10.1 逻辑覆盖法

逻辑覆盖法是针对软件内部的逻辑结构设计测试用例的。由于无法完全测试软件的所有路径,所以逻辑覆盖法采用逐级覆盖的办法,在每一级上有选择地执行某些路径,如此一级一级地进行覆盖,逐步使路径测试达到尽可能完善的程度。

覆盖级别由低到高可以划分为:

(1)语句覆盖:每个语句至少执行一次。

(2)判定覆盖:对于每个判定语句,执行真假两种结果。

(3)条件覆盖:使判定表达式中的每个简单条件都取到各种可能的结果。

(4)判定/条件覆盖:使判定表达式中的每个简单条件取到各种可能的值,并且使每个判定也都取到各种可能的结果。

(5)条件组合覆盖:使判定表达式中的简单条件能够得到各种可能的组合情况。

应当引起注意的是,随着测试级别的提高,测试用例的数据量会急剧增加。

1.语句覆盖

所谓语句覆盖,就是选择足够的测试用例,使程序中的每个语句至少执行一次。例如:


float test(float A, float B, float X) {           if ((A>1)&&(B= =0))                 X=X/A;           if ((A= =2)||(X>1))                 X=X+1;           return X;}  

这是一个被测试模块的源程序,它的流程图如图13-14所示。为了使模块中的每个语句都执行一次,只需设计一个能通过路径sacbed的测试用例即可,例如下面一组测试数据


A=2,B=0,X=3  

虽然能够覆盖程序中的所有语句,但它对程序逻辑却覆盖得很少。因为数据只对两个判断条件为真进行了测试,如果条件为假,显然不能发现错误。此外,如果将第一个判断语句中的条件“&&”误写成“||”,或者将第二个判断语句中的X>l误写成X>0,该测试用例无法暴露这些错误。由此可见,语句覆盖是一种很弱的覆盖标准。

图13-14 被测试模块流程图

2.判定覆盖

判定覆盖亦称分支覆盖,即选择足够的测试用例,使程序中的每个判定的各个分支至少执行一次。

对于上述被测试模块,如果设计两个测试用例,使它们分别通过路径sacbd和sabed,或者分别通过路径sacbed和sabd,就可以满足判定覆盖标准。这样的测试用例可以设计成:

(1)A=3,B=0,X=3(通过路径sacbed)

(2)A=2,B=l,X=l(通过路径sabd)

显然,判定覆盖比语句覆盖严格,因为如果每个分支都执行过了:那么每个语句也就执行过了。但是,它对程序逻辑的覆盖程度仍然不高。例如,如果将第二个判定语句中的X>l误写成X>0,这两个测试用例仍无法发现该错误。

3.条件覆盖

一个判定的条件表达式往往是一个由若干简单条件所组成的复合条件。例如前例中的条件表达式(A>l)&&(B==0),由两个简单条件A>l、B==0和逻辑运算符“&&”构成。所以,对于复合条件的判定采用判定覆盖标准进行测试,显然不够严格。为此,可以采用一个更强的覆盖标准——条件覆盖,即选择足够多的测试用例,使得判定中的每个简单条件都取到各种可能的结果。

在图13-14的例子中,共有两个判定,每个判定的条件表达式都由两个简单条件组成。为了满足条件覆盖标准,所选择的测试用例应当使得在a点出现下述各种结果:

A>l,A≤l,B=0,B≠0

在b点应当出现的结果是:

A=2,A≠2,X>l,X≤l

只需使用以下两个测试用例就可以满足这些条件:

(1)A=2,B=0,X=4(通过路径sacbed,在a点满足A>l,B=0;在b点满足A=2,X>l)

(2)A=l,B=l,X=l(通过路径sabd,在a点满足A≤l,B≠0;在b点满足A≠2,X≤l)

一般说来,条件覆盖比判定覆盖严格,因为它使条件表达式中的每个简单条件都取得了两种不同的结果,而判定覆盖则不保证这一点。但是,也可能出现相反的情况,即满足条件覆盖标准,却不满足判定覆盖标准。例如,以下两个测试用例就是这种情况,它使得第二个判定的条件表达式总为真:

(1)A=2,B=0,X=l(通过路径sacbed,在a点满足A>1,B=0;在b点满足A=2,X≤l)

(2)A=l,B=l,X=2(通过路径sabed,在a点满足A≤l,B≠0;在b点满足A≠2,X>l)

4.判定/条件覆盖

针对上面的问题,可以采用另一种覆盖标准,这就是判定/条件覆盖。它的含义是,选择足够的测试用例,使得判定表达式中的每个简单条件取到各种可能的值,并且使每个判定也都取到各种可能的结果。

对于图13-14中的程序,下面两个测试用例满足判定/条件覆盖标准:

(1)A=2,B=0,X=4

(2)A=l,B=l,X=l

这两组数据就是为了满足条件覆盖标准最初选用的测试用例。因此,判定/条件覆盖有时并不比条件覆盖强多少。

5.条件组合覆盖

条件组合覆盖是更强的覆盖标准,它要求选择更多的测试用例,以便使每个判定表达式中的简单条件能够取到各种可能的组合情况。

对于图13-14中的程序,共有下面8种可能的条件组合:


(1)A>l,B=0   (2)A>l,B≠0   (3)A≤l,B=0    (4)A≤l,B≠0(5)A=2,X>l   (6)A=2,X≤l   (7)A≠2,X>l    (8)A≠2,X≤l  

为了使这8种条件组合至少出现一次,可以使用以下4组测试数据:


(1)A=2,B=0,X=4 (针对1、5两种组合,通过路径sacbed)(2)A=2,B=l,X=l (针对2、6两种组合,通过路径sabed)(3)A=l,B=0,X=2 (针对3、7两种组合,通过路径sabed)(4)A=l,B=l,X=l (针对4、8两种组合,通过路径sabd)。  

显然,满足条件组合覆盖标准的测试用例,一定满足判定覆盖、条件覆盖和判定/条件覆盖标准。因此,条件组合覆盖标准是最强的一种覆盖标准。但是,满足条件组合覆盖标准的测试用例,不一定能通过程序中的所有路径。例如,上述4组测试用例,就没有测试到路径sacbd。

一般说来,条件组合覆盖标准比其他标准优越。但是任何一种逻辑覆盖标准都不足以成为唯一的测试标准,还需要用其他的测试方法加以补充。

13.10.2 等价划分法

等价划分是一种黑盒测试设计技术。其目的在于系统性地确定测试用例,从而使得到的测试用例对发现某类错误有极高的概率。

这种方法建立在以下的假定基础之上。如果将软件输入数据的可能值划分成若干类,每一类的一个典型值在测试中的作用与这一类中所有其他值的作用等价。也就是说,如果某一类中的一个例子发现了错误,那么该等价类中的其他例子也能发现同样的错误;反之,如果某一类中的一个例子没有发现错误,那么该等价类中的其他例子也不会发现错误。因此,采用等价划分方法测试软件,只需从每个等价类中选择一组数据作为测试用例,从而实现了用较少的测试用例发现尽可能多的错误。

使用等价划分法设计测试用例,首先必须按照软件的功能说明分析输入条件,确定输入数据的各种有效等价类和无效等价类。合理等价类,系指软件合理的一类输入数据;不合理等价类,系指非法的一类输入数据。

划分等价类在很大程度上取决于软件人员的经验。一般说来,以下几条原则可作为划分等价类的依据:

(1)输入条件中规定了输入数据的取值范围,则可据此划分出一个合理等价类和两个不合理等价类。例如,考试成绩的取值范围是从0至100,那么合理的等价类为大于等于0且小于等于100的数,小于0的数和大于100的数均为不合理的等价类。

(2)输入条件中规定了输入数据的个数,则可据此划分出一个合理等价类和两个不合理等价类。例如,体育比赛取前三名的成绩(不考虑并列第几名的情况),那么,合理的等价类为三个输入数据,而小于三个输入数据以及大于三个输入数据均为不合理的等价类。

(3)输入条件中规定了输入数据必须遵循的规则,则可据此划分出一个合理等价类和若干个不合理等价类。例如,标识符的规则有一条是第一个字符必须是字母,那么第一个字符为字母者为合理的等价类,而第一个字符为数字以及其他特殊符号者为不合理等价类。

(4)若输入条件中规定了输入数据的一组值,而且软件对不同的输入值采取不同的处理,则每个允许的输入值是一个合理的等价类,其他值则为不合理的等价类。例如,正高级职称的输入值分教授、研究员和教授级高级工程师三种,那么每一种职称可以作为一个等价类,而除上述三种职称之外的值为不合理的等价类。

(5)若规定输入数据为整型,则可以划分为正整数、零和负整数三个合理等价类,而小数则为不合理的等价类。

划分出输入数据的等价类以后,便可根据等价类设计测试用例。设计测试用例时应按以下四个步骤来进行:

(1)设计一个新的测试用例,使它尽可能多地涉及那些尚未被涉及的合理等价类;

(2)重复第一步,直至新选择的测试用例己涉及了所有的合理等价类;

(3)设计一个新的测试用例,使它涉及一个尚未被涉及的不合理等价类;

(4)重复第三步,直至所选择的测试用例已涉及了所有的不合理等价类。

需要指出的是,在选择不合理等价类的测试用例时,应使每个例子仅涉及一个不合理等价类。这是因为,软件中的一个错误条件往往会抑制对其他错误条件的检测。一个例子涉及两个以上的不合理等价类,就会使一部分软件功能没有被测试到。

13.10.3 边值分析法

经验表明,软件在处理边缘情况时容易发生错误。例如,在下标、数据结构、标量和循环变量取最大值、最小值及其临界值时往往出现错误。因此,使用针对这个区域的测试用例,能提高软件测试发现错误的概率。这种测试用例的设计方法称为边值分析法。

运用边值分析法设计测试用例依赖软件人员的经验和创造性。一般来说,以下几条原则可用做选择测试用例的依据:

(1)若输入条件中规定了输入数据的取值范围,则可在合理等价类中选择一些恰到好处且刚刚处于范围之内的边界值的例子。另外再从不合理等价类中选择一些恰好越过边界的例子。例如,输入值的范围是-1.0~1.0,则可选择-1.0、1.0、-0.99、-1.01和1.01作为测试用例。

(2)若输入条件中规定了输入数据的个数,则可选择最小个数、最大个数,比最大个数多1、比最小个数少1、比最小个数多1、比最大个数少1等几种情况设计测试用例。例如,在输入字符串时,规定字符串可由1~256个字符组成,则可分别设计有1个字符、256个字符、2个字符、255个字符、0个字符和257个字符的用例。

(3)若输入数据为有序集合结构,如顺序文件、线性表等,则应特别注意对集合的第一个、最后一个元素以及空集设计测试用例。

边值分析法不同于等价划分法,它不是从一个等价类中任选一个例子作代表,而是选一个或几个例子,使得该等价类的边界条件成为测试的主要目标。此外,边值分析法不仅注意输入条件,它还根据输出条件,即输出的等价类设计测试用例。但是,由于输入值的边界不一定与输出值的边界相对应,所以要设计出使输出处于边界条件的测试用例住往是很困难的。尽管如此,在设计测试用例时考虑到这种情况仍然是十分重要的。

13.10.4 因果图法

等价划分法和边值分析法的缺点是没有测试输入条件的组合。往往存在这一种情况,虽然分别使用每组测试用例时,软件都能正常工作,但是输入数据的某种组合却能暴露出错误。不过,要检查所有输入条件的组合并非容易,即使是一个比较小的程序或模块,可能的输入条件的组合数目也往往十分巨大。如果没有一种系统的方法是难以设计条件组合测试用例的。这种方法就是因果图法。它利用输入条件(即原因)和输出或程序状态的改变(即效果)之间的逻辑关系设计测试用例,以便实现输入条件的组合测试。

用因果图法设计测试用例按以下四个步骤进行:

(1)为一个程序列出原因(输入条件)和效果(输出或程序状态)并为每个原因和效果规定一个标识符;

(2)绘制因果图;

(3)将因果图转换成判定表;

(4)按判定表的每一规则设计一个测试用例。

13.10.5 错误猜测法

使用等价划分法和边值分析法可以设计出具有代表性的测试用例。但是,不同类型和不同特点的软件通常又有一些特殊的容易出错的情况。对于这些情况往往无法采用特定的技术来设计测试用例,只能靠软件人员的经验和直觉来推测软件中可能存在的各种错误,从而针对这些错误设计测试用例,这就是错误猜测法。

错误猜测法没有确定的原则,一般要凭经验来假定错误类型。例如本章列举的编码错误及模块测试内容,就是常见的软件错误的经验总结。又如,输入数据为零或输出数据为零;输入表格为空或只有一项;输入参数具有默认值等均是容易出错的地方。

此外,对于解决特定问题的软件,应根据其功能,猜测软件设计中容易忽视的情况。例如,对于排序程序应着重检测:①输入表为空;②输入表中只有一项;③输入表中所有的项具有相同的值;④输入表已经是排序的或逆序的。对于一个采用二分法的查询程序应着重检测:①被查询的表只有一项;②表的项数恰好等于2的幂次;③表的项数比2的幂次多1或少1;④被查询的值正好在表中的第一项、最后一项或中间项。这些均是设计时往往被忽视而处理中易出错的情况。