最小值,其中k<i
期望结果:基于k的正确平均值和总数
路径5测试用例:
value(i)=有效输入,其中i<100
value(k)>最大值,其中k≥i
期望结果:基于k的正确平均值和总数
路径6测试用例:
value(i)=有效输入,其中i<100
期望结果:基于k的正确平均值和总数
执行每个测试用例,并和期望值比较,一旦完成所有测试用例,测试者可以确定在程序中的所有语句至少被执行一次。
重要的是要注意,某些独立路径(如,例子中的路径1)不能以独立的方式被测试,即,穿越路径所需的数据组合不能形成程序的正常流,在这种情况下,这些路径必须作为另一个路径测试的一部分来进行测试。
16.4.4 图矩阵
导出流图和决定基本测试路径的过程均需要机械化,为了开发辅助基本路径测试的软件工具,称为图矩阵(graph matrix)的数据结构很有用。
图矩阵是一个正方形矩阵,其大小(即列数和行数)等于流图的节点数。每列和每行都对应于标识的节点,矩阵项对应于节点间的连接(边),图16-7显示了一个简单的流图及其对应的图矩阵[BEI90]。
该图中,流图的节点以数字标识,边以字母标识,矩阵中的字母项对应于节点间的连接,例如,边b连接节点3和节点4。
这里,图矩阵只是流图的表格表示,然而,对每个矩阵项加入连接权值(link weight),图矩阵就可以用于在测试中评估程序的控制结构,连接权值为控制流提供了另外的信息。最简单情况下,连接权值是 1(存在连接)或0(不存在连接),但是,连接权值可以赋予更有趣的属性:
·执行连接(边)的概率。
·穿越连接的处理时间。
·穿越连接时所需的内存。
·穿越连接时所需的资源。
举例来说,我们用最简单的权值(0或1)来标识连接,图16-7所示的图矩阵重画为图16-8。字母替换为1,表示存在边(为清晰起见,没有画出0),这种形式的图矩阵称为连接矩阵(linkmatrix)。图16-8中,含两个或两个以上项的行表示判定节点,所以,右边所示的算术计算就提供了另一种环形复杂性计算(参16.4.2节)的方法。
Beizer[BEI90]提供了可用于图矩阵的其他数学算法的处理,利用这些技术,设计测试用例的分析就可以自动化或部分自动化。
16.5 控制结构测试
16.4节所述的基本路径测试技术是控制结构测试技术之一。尽管基本路径测试简单高效,但是,其本身并不充分。本节讨论控制结构测试的其他变种,这些测试覆盖并提高了白盒测试的质量。
16.5.1 条件测试
条件测试是检查程序模块中所包含逻辑条件的测试用例设计方法。一个简单条件是一个布尔变量或一个可能带有NOT(“┓”)操作符的关系表达式。关系表达式的形式如:
E1<关系操作符>E2
其中E1和E2是算术表达式,而<关系操作符>是下列之一:“<”,“≤”,“=”,“≠”(“┓=”),“>”,或“≥”。复杂条件由简单条件、布尔操作符和括弧组成。我们假定可用于复杂条件的布尔算子包括OR“|”,AND“&”和NOT“┓”,不含关系表达式的条件称为布尔表达式。
所以条件的成分类型包括布尔操作符、布尔变量、布尔括弧(括住简单或复杂条件)、关系操作符或算术表达式。
如果条件不正确,则至少有一个条件成分不正确,这样,条件的错误类型如下:
·布尔操作符错误(遗漏布尔操作符,布尔操作符多余或布尔操作符不正确)。
·布尔变量错误。
·布尔括弧错误。
·关系操作符错误。
·算术表达式错误。
条件测试方法注重于测试程序中的条件。本节后面讨论的条件测试策略主要有两个优点,首先,测度条件测试的覆盖率是简单的,其次,程序的条件测试覆盖率为产生另外的程序测试提供了指导。
条件测试的目的是测试程序条件的错误和程序的其他错误。如果程序P的测试集能够有效地检测P中的条件错误,则该测试集可能也会有效地检测P中的其他错误,此外,如果测试策略对检测条件错误有效,则它也可能有效地检测程序错误。
已经提出了几个条件测试策略。分支测试可能是最简单的条件测试策略,对于复合条件C,C的真分支和假分支以及C中的每个简单条件都需要至少执行一次[MYE97]。
域测试(Domain testing)[WHI80]要求从有理表达式中导出三个或四个测试,有理表达式的形式如:
E1<关系操作符>E2
需要三个测试分别用于计算E1的值是大于、等于或小于E2的值[HOW82]。如果<关系操作符>错误,而E1和E2正确,则这三个测试能够发现关系算子的错误。为了发现E1和E2的错误,计算E1小于或大于E2的测试应使两个值间的差别尽可能小。
有n个变量的布尔表达式需要2n个可能的测试(n>0)。这种策略可以发现布尔操作符、变量和括弧的错误,但是只有在n很小时实用。
也可以派生出敏感布尔表达式错误的测试[FOS84,TAI87]。对于有n个布尔变量(n>0)的单布尔表达式(每个布尔变量只出现一次),可以很容易地产生测试数小于2n的测试集,该测试集能够发现多个布尔操作符错误和其他错误。
Tai[TAI89]建议在上述技术之上建立条件测试策略,称为BRO(branch and relational试集operator)的测试保证能发现布尔变量和关系操作符只出现一次而且没有公共变量的条件中的分支和条件操作符错误。
BRO策略利用条件C的条件约束。有n个简单条件的条件C的条件约束定义为(D1,D2,…,Dn),其中Di(0<i≤n)表示条件C中第i个简单条件的输出约束。如果C的执行过程中C的每个简单条件的输出都满足D中对应的约束,则称条件C的条件约束D由C的执行所覆盖。
对于布尔变量B,B输出的约束说明B必须是真(t)或假(f)。类似地,对于关系表达式,符 <、=、>用于指定表达式输出的约束。
作为简单的例子,考虑条件
C1∶B1&B2
其中B1和B2是布尔变量。C1的条件约束式如(D1,D2),其中D1和D2是“t”或“f”,值(t,f)是C1的条件约束,由使B1为真B2为假的测试所覆盖。BRO测试策略要求约束集{(t,t),(f,t),(t,f)}由C1的执行所覆盖,如果C1由于布尔算子的错误而不正确,至少有一个约束强制C1失败。
作为第二个例子,考虑
C2∶B1&(E3=E4)
其中B1是布尔表达式,而E3和E4是算术表达式。C2的条件约束形式如(D1,D2),其中D1是“t”或“f”,D2是<,=或>。除了C2的第二个简单条件是关系表达式以外,C2和C1相同,所以可以修改C1的约束集{(t,t),(f,t),(t,f)},得到C2的约束集,注意(E3=E4)的“t”意味着“=”,而(E3=E4)的“f”意味着“>”或“<”。分别用(t,=)和(f,=)替换(t,t)和(f,t),并用(t,<\<>)和(t,>)替换(t,f),就得到C2的约束集{(t,=),(f,=),(t,<),(t,>)}。上述条件约束集的覆盖率将保证检测C2的布尔和关系算子的错误。
作为第三个例子,考虑
C3∶(E1>E2)&(E3=E4)
其中E1、E2、E3和E4是算术表达式。C3的条件约束形式如(D1,D2),其中D1和D2是<、=或>。除了C3的第一个简单条件是关系表达式以外,C3和C2相同,所以可以修改C2的约束集得到C3的约束集,结果为
{(>,=),(=,=),(<,=),(>,>),(>,<)}
上述条件约束集能够保证检测C3的关系操作符的错误。
16.5.2 数据流测试
数据流测试方法按照程序中的变量定义和使用的位置来选择程序的测试路径。已经有不少关于数据流测试策略的研究(如参考文献[FRA88]、[NTA88]和[FRA93])。肪丁R丫胁簧*
为了说明数据流测试方法,假设程序的每条语句都赋予了独特的语句 ,而且每个函数都不改变其参数和全局变量。对于语句 为S的语句,
DEF(S)={X|语句S包含X的定义}
USE(S)={X|语句S包含X的使用}
如果语句S是if或循环语句,它的DEF集为空,而USE集取决于S的条件。如果存在从S到S′的路径,并且该路径不含X的其他定义,则称变量X在语句S处的定义在语句S′仍有效。
变量X的定义—使用链(或称DU链)形式如[X,S,S′],其中S和S′是语句 ,X在DEF(S)和USE(S′)中,而且语句S定义的X在语句S′有效。
一种简单的数据流测试策略是要求覆盖每个DU链至少一次。我们将这种策略称为DU测试策略。已经证明DU测试并不能保证覆盖程序的所有分支,但是,DU测试不覆盖某个分支仅仅在于如下之类的情况:if-then-else中的then没有定义变量,而且不存在else部分。这种情况下,if语句的else分支并不需要由DU测试覆盖。
数据流测试策略可用于为包含嵌套if和循环语句的程序选择测试路径,为此,考虑使用DU测试为如下的PDL选择测试路径:
proc x
B1;
do while C1
if C2
then
if C4
then B4;
else B5;
endif;
else
if C3
then B2;
else B3;
endif;
endif;
enddo;
B6;
end proc;
为了用DU测试选择控制流图的测试路径,需要知道PDL条件或块中的变量定义和使用。假设变量X定义在块B1,B2,B3,B4和B5的最后一条语句之中,并在块B2,B3,B4,B5和B6的第一条语句中使用。DU测试策略要求执行从每个B(0<i≤5)到Bj(0<j≤6)的最短路径(这样的测试也覆盖了条件C1,C2,C3和C4中的变量使用)。尽管有25条X的DU链,只需5条路径覆盖这些DU链。原因在于可用5条从Bi(0<i≤5)到B6的路径覆盖X的链,而这5条链包含循环的迭代就可以覆盖其他的DU链。
注意如果要用分支测试策略为上述的PDL选择测试路径,并不需要另外的信息。为了选择BRO测试的路径,只需知道每个条件和块的结构。(选择程序的路径之后,需要决定该路径是否实用于该程序,即是否存在执行该路径的至少一个输入)。
由于变量的定义和使用,程序中的语句都彼此相关,所以数据流测试方法能够有效地发现错误,但是,数据流测试的覆盖率测度和路径选择比条件测试更为困难。
16.5.3循环测试
循环是大多数软件实现算法的重要部分,但是,在软件测试时却很少注意它们。
循环测试是一种白盒测试技术,注重于循环构造的有效性。有四种循环[BEI90]:简单循环,串接循环,嵌套循环和不规则循环(如图16-9所示)。
简单循环。下列测试集应当用于简单循环,其中n是允许通过循环的最大次数。
1.整个跳过循环。
2.只有一次通过循环。
3.两次通过循环。
4.m次通过循环,其中m<n。
5.n-1,n,n+1次通过循环。
嵌套循环。如果要将简单循环的测试方法用于嵌套循环,可能的测试数就会随嵌套层数成几何级增加,这会导致不实际的测试数目,Beizer[BEI90]提出了一种减少测试数的方法:*
1.从最内层循环开始,将其他循环设置为最小值。
2.对最内层循环使用简单循环测试,而使外层循环的迭代参数(即循环计数)最小,并为范围外或排除的值增加其他测试。
3.由内向外构造下一个循环的测试,但其他的外层循环为最小值,并使其他的嵌套循环为“典型”值。
4.继续直到测试完所有的循环。
串接循环。如果串接循环的循环都彼此独立,可以使用嵌套循环的策略测试串接循环。但是,如果两个循环串接起来,而第一个循环的循环计数是第二个循环的初始值,则这两个循环并不是独立的。如果循环不独立,则推荐使用嵌套循环的方法进行测试。
不规则循环。尽可能的情况下,要将这类循环重新设计为结构化的程序结构(参第14章)。
16.6黑盒测试
黑盒测试注重于测试软件的功能性需求,也即黑盒测试使软件工程师派生出执行程序所有功能需求的输入条件。黑盒测试并不是白盒测试的替代品,而是用于辅助白盒测试发现其他类型的错误。
黑盒测试试图发现以下类型的错误:(1)功能不对或遗漏,(2)界面错误,(3)数据结构或外部数据库访问错误,(4)性能错误和(5)初始化和终止错误。
白盒测试在测试的早期执行,而黑盒测试主要用于测试的后期(参第17章)。黑盒测试故意不考虑控制结构,而是注意信息域。测试用于回答以下问题:
·如何测试功能的有效性p>
·何种类型的输入会产生好的测试用例p>
·系统是否对特定的输入值尤其敏感p>
·如何分隔数据类的边界p>
·系统能够承受何种数据率和数据量p>
·特定类型的数据组合会对系统产生何种影响p>
运用黑盒测试,可以导出满足以下标准的测试用例集[MYE79]:(1)所设计的测试用例能够减少达到合理测试所需的附加测试用例数,和(2)所设计的测试用例能够告知某些类型错误的存在或不存在,而不是仅仅与特定测试相关的错误。
16.6.1 基于图的测试方法
黑盒测试①的第一步是理解软件所表示的对象②及其关系,然后,第二步是定义一组保证“所有对象与其他对象都具有所期望的关系”[BEI95]的测试序列,换而言之,软件测试首先是创建对象及其关系图,然后导出测试序列以检查对象及其关系,并发现错误。
为了完成这些步骤,软件工程师首先创建一个图,节点代表对象,连接代表对象间的关系,节点权值描述节点的属性(如特定的数据值或状态行为),连接权值描述连接的特点①。
图的符 表示如图16-10a所示。节点表示为圆,而连接有几种,有向连接(有箭头表示)表明关系只在一个方向上存在。双向连接,也称为对称连接,表示关系适于两个方向。如果节点间有几种联系,就使用并行边。
举一个简单的例子,考虑部分字处理应用程序图,如图16-10b所示:
对象#1=新建文件菜单选择
对象#2=文档窗口
对象#3=文档文本
如图所示,选择菜单“新建文件”产生一个文档窗口,文档窗口的节点权值提供窗口产生时所期望的属性集,连接权值表明窗口必须在1.0秒之内产生,一条无向边在“选择菜单新建文件”和“文档文本”之间建立对称联系,并行连接表明“文档窗口”和“文档文本”间的联系,事实上,要产生测试用例还需要更加详细的图。软件工程师遍历图,并覆盖所显示的联系就可以导出测试用例,这些用例用于发现联系之间的错误。
Beizer[BEI95]描述了几个使用图的行为测试方法:
事务流建模。节点代表事务的步数(如使用联机服务预订航空机票的步数),连接代表步骤之间的连接关系(如flighgt.information.input后跟validation/availabilty.processing)。数据流图(参见第12章)可用于辅助产生这种图。
有限状态建模。节点代表不同用户可见的软件状态(如订票人员处理订票时的各个屏幕),而连接代表状态之间的转换(如order-information在inventory-availability-look-up时验证并后跟customer-billing-information-input)。状态变迁图(参见第12章)可用于辅助产生这种图。
数据流建模。节点是数据对象,而连接是将数据对象转换为其他对象时发生的变换。例如,节点FICA.tzx.withheld(FTW)由gross.wagess(GW)利用关系FTW=0.062×GW计算而来。
时间建模。节点是程序对象,而连接是对象间的顺序连接。连接权值用于指定程序执行时所需的执行时间。
基于图的测试方法的详细讨论超出了本书的范围,感兴趣的读者可以阅读(见参考文献[BEI95])一书。但是,大致了解一下基于图的测试还是值得的。
基于图的测试开始定义节点和节点权值,也即标识对象及其属性,数据模型(参见第12章)可以作为起始点,但是要注意很多节点是程序对象(不在数据模型中时显表示出来),为了标识图的起点和终点,可以定义入点和出点。
标识节点以后,就可以建立连接及其权值,连接一般应当命名,但是当代表程序对象间控制流的连接时除外。
很多情况下,图模型可能有循环(如图的路径含有环),循环测试(参见16.5.3节)也可用于行为(黑盒)测试,图可用于标识需要测试的循环。
分别研究每个关系,以导出测试用例。研究顺序关系的传递性可以发现关系在对象间传播的影响。举例说明,有三个对象X,Y和Z。考虑如下关系:
计算Y需要X
计算Z需要Y
所以,X和Z之间有传递性:
计算Z需要X
基于这种传递性,测试Z的计算时要考虑X和Y的各种值。
关系(图连接)的对称性也是设计测试用例的重要考虑,如果关系是双向(对称)的,就要测试这种性质。很多应用程序的UNDO功能[BEI95]实现了有限的对称性,应该彻底测试并标识鸵馑械囊斐#床荒苁褂肬NDO的地方)。最后,图的每个节点都应当有到自己的关系,本质上是“空操作”循环,自反性也应当进行测试。
开始设计测试用例时,第一个目标是节点的覆盖度,这意味着测试不应当遗漏某个节点,而且节点的权值是正确的。
接着,考虑连接的覆盖率,基于属性测试每个关系,例如,测试对称关系以表明它的确是双向的,测试传递关系以表明存在传递性,测试自反关系以表明存在空操作。指明连接权值时,要设计测试以展示权值是否有效,最后,加入循环测试(参见16.5.3节)。
16.6.2 等价划分
等价划分是一种黑盒测试方法,将程序的输入域划分为数据类,以便导出测试用例。理想的测试用例是独自发现一类错误(如字符数据的处理不正确)。等价划分试图定义一个测试用例以发现各类错误,从而减少必须开发的测试用例数。
等价划分的测试用例设计基于输入条件的等价类评估。使用前面章节介绍的概念,如果对象由具有对称性、传递性或自反性的关系连接,就存在等价类[BEI95]。等价类表示输入条件的一组有效或无效的状态。典型地,输入条件通常是一个特定的数值,一个数值域,一组相关值或一个布尔条件。可按照如下指南定义等价类:
1.如果输入条件代表一个范围,可以定义一个有效等价类和两个无效等价类。
2.如果输入条件需要特定的值,可以定义一个有效等价类和两个无效等价类。
3.如果输入条件代表集合的某个元素,可以定义一个有效等价类和一个无效等价类。
4.如果输入条件是布尔式,可以定义一个有效等价类和一个无效等价类。
作为例子,考虑自动银行应用软件所维护的数据,用户可以用自己的微机拨 到银行,提供六位数的密码,并遵循一序列键盘命令以触发各种银行功能。银行应用程序的软件可以接受如下格式的数据:
区 ——空或三位数字。
前缀——三位数字,但不是0和1开始。
后缀——四位数字。
密码——六位字母或数字。
命令——“检查”,“存款”,“付款”等。
与银行应用程序各种数据元素相关的输入条件可以表示为:
区 :输入条件,布尔——区 存在与否。
输入条件,范围——定义在200和999之间的数值,少数例外。
前缀:输入条件,范围——大于200不含0的数值。
后缀:输入条件,值——四位数字。
密码:输入条件,布尔——密码存在与否。
输入条件,值——六位字符串。
命令:输入条件,集合——包含上述命令。
利用上述导出等价类的指南,就可以为每个输入域的数据项开发并执行测试用例,测试用例的选择最好是每次执行最多的等价类属性。
16.6.3边界值分析
由于某些未被完全知道的原因,输入域的边界比中间更加容易发生错误,为此,可用的边界值分析(boundary value analysis,BVA)可作为一种测试技术。边界值分析选择一组测试用例检查边界值。
边界值分
相关资源:数囊生鲜配送管理系统_单机版.rar-管理软件文档类资源-CSDN文库
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!