虽然软件测试技术在不断地发展,但传统的分类方法仍然适用。按使用的测试技术不同可以将测试分为静态测试和动态测试,进一步地可以将静态测试分成静态分析和代码审查,将动态测试分成白盒测试和黑盒测试。
代码审查(包括代码评审和走查)主要依靠有经验的程序设计人员根据软件设计文档,通过阅读程序,发现软件错误和缺陷。代码审查一般按代码审查单阅读程序,查找错误。代码审查的内容包括:检查代码和设计的一致性;检查代码的标准性、可读性:检查代码逻辑表达的正确性和完整性;检查代码结构的合理性等。代码审查虽然在发现程序错误上有一定的局限性,但它不需要专门的测试工具和设备,且有一旦发现错误就能定位错误和一次发现一批错误等优点。
静态分析主要对程序进行控制流分析、数据流分析、接口分析和表达式分析等。静态分析一般由计算机辅助完成。静态分析的对象是计算机程序,程序设计语言不同,相应的静态分析工具也就不同。目前具备静态分析功能的软件测试工具有很多,如Purify,Macabe等。
白盒测试是一种按照程序内部的逻辑结构和编码结构设计并执行测试用例的测试方法。采用这种测试方法,测试者需要掌握被测程序的内部结构。白盒测试通常根据覆盖准则设计测试用例,使程序中的每个语句、每个条件分支、每个控制路径都在程序测试中受到检验。白盒测试需要运行程序,并能在运行过程中跟踪程序的执行路径。软件人员使用白盒测试方法,主要想对程序模块进行如下的检查:
·对程序模块的所有独立的执行路径至少测试一次;
·对所有的逻辑判定,取“真”与取“假”的两种情况都能至少测试一次
·在循环的边界和运行界限内执行循环体
·测试内部数据结构的有效性,等等。
黑盒测试是一种从软件需求出发,根据软件需求规格说明设计测试用例,并按照测试用例的要求运行被测程序的测试方法。它较少关心程序内部的实现过程,侧重于程序的执行结果,将被测程序看成是不可见的黑盒子,因此被称为黑盒测试。黑盒测试着重于验证软件功能和性能的正确性,它的典型测试项目包括功能测试、性能测试、边界测试、余量测试和强度测试等。黑盒测试主要是为了发现以下几类错误:
·是否有不正确或遗漏了的功能
·在接口上,输入能否正确地接受?能否输出正确的结果?
·是否有数据结构错误或者外部信息(例如数据文件)访问错误?
·性能上是否能够满足要求?
·是否有初始化或终止性错误?
逻辑覆盖是以程序内部的逻辑结构为基础的测试用例设计技术,属白盒测试。这一方法要求测试员对程序的逻辑结构有清楚的了解。由于覆盖测试的目标不同,逻辑覆盖可分为:语句覆盖、判定覆盖、判定-条件覆盖、条件组合覆盖及路径覆盖。以下分别介绍。
(1)语句覆盖
语句覆盖就是设计若干个测试用例,运行所测程序,使得每一可执行语句至少执行一次。从程序中每个可执行语句都得到执行这一点来看,语句覆盖的方法似乎能够比较全面地检验每一个可执行语句。但需要注意的是,这种覆盖也绝不是完美无缺的。虽然做到了语句覆盖,但可能发现不了判断中逻辑运算中出现的错误。与后面所介绍的其他覆盖相比,语句覆盖是最弱的逻辑覆盖准则。
(2)判定覆盖
判定覆盖设计若干个测试用例,运行所测程序,使得程序中每个判断的取真分支和取假分支至少经历一次。判定覆盖又称为分支覆盖。判定覆盖的测试用例的取法不唯一,有例外情形,只是判定覆盖,还不能保证一定能查出在判断的条件中存在的错误。因此需要更强的逻辑覆盖准则去检验判断内部条件。
(3) 条件覆盖
条件覆盖就是设计若干个测试用例,运行所测程序,使得程序中每个判断的每个条件的可能取值至少执行一次。条件覆盖的测试用例有不但覆盖了所有判断的取真分支和取假分支,而且覆盖了中所有条件的可能取值的用例,也有虽满足了条件覆盖,但只覆盖部分条件的用例,不满足判定覆盖的要求。为解决这一矛盾,需要对条件和分支兼顾,有必要考虑以下的判定-条件覆盖。
(4)判定-条件覆盖
判定-条件覆盖就是设计足够的测试用例,使得判断中每个条件的所有可能取值至少执行一次,同时每个判断的所有可能判断结果至少执行一次。换言之,即是要求各个判断的所有可能的条件取值组合至少执行一次。判定-条件覆盖也有缺陷。从表面上来看,它的测试用例测试了所有条件的取值。但事实并非如此。因为往往某些条件掩盖了另一些条件。因此,采用判定-条件覆盖,逻辑表达式的错误不一定能够查得出来。
(5)条件组合覆盖
条件组合覆盖就是设计足够的测试用例,运行所测程序,使得每个判断的所有可能的条件取值组合至少执行一次。对于每个判断,要求所有可能的条件取值的组合都必须取到。但条件组合覆盖的测试用例覆盖了所有条件的可能取值的组合,覆盖了所有判断的分支,但也会漏掉了某些路径的。测试还不完全。
(6)路径测试
路径测试就是设计足够的测试用例,覆盖程序中所有可能的路径。
在实际问题中,一个不太复杂的程序,其路径都是一个庞大的数字。要在测试中覆盖这样多的路径是不现实的。为解决这一难题,只是把覆盖的路径数压缩到一定限度内,例如:程序中的循环只执行一次。基本路径测试就是这样的一种测试方法,它是在程序控制流图的基础上,通过分析控制构造的环路复杂性,导出基本可执行路径集合,从而设计测试用例的方法。设计出来的测试用例要保证在测试中程序的每一个可执行语句至少执行一次。
(1)程序的控制流图
(2)程序环路复杂性
(3)导出测试用例
基本路径测试法适用于模块的详细设计及源程序,其主要程序步骤如下:
①以详细设计或源代码作为基础,导出程序的控制流图
②计算得到的控制流图G的环路复杂性V(G)
③确定线性无关的路径的基本集
④生成测试用例,确保基本路径集中每条路径的执行
等价类划分是一种典型的黑盒测试方法,也是一种非常实用的重要测试方法。使用这一方法时,完全不考虑程序的内部结构,只依据程序的规格说明来设计测试用例。
(1)划分等价类
等价类是指某个输入域的子集合。在该子集合中,各个输入数据对于揭露程序中的错误都是等效的。并合理地假定:测试某等价类的代表值就等价于对这一类其他的测试。如果某个等价类中的一个输入条件作为测试数据进行测试查出了错误,那么使用这一等价类中的其他输入条件进行测试也会查出同样的错误;反之,若使用某个等价类中一个输入条件作为测试数据进行测试没有查出错误,则使用这个等价类中的其他输入条件也同样查不出错误。
等价类的划分有两种不同的情况:
①有效等价类:是指对于程序的规格说明来说,是合理的,有意义的输入数据构成的集合。利用它,可以检验程序是否实现了规格说明预先规定的功能和性能。
②无效等价类:是指对于程序的规格说明来说,是不合理的,无意义的输入数据构成的集合。程序员主要利用这一类测试用例检查程序中功能和性能的实现是否不符合规格说明要求。
划分等价类的原则:
①如果输入条件规定了取值范围,或值的个数,则只可以确立一个有效等价类和两个无效等价类。例如:在程序规格说明中,结输入条件有一个规定:“项数可以从1到999”,则有效等价类是“1≤项数≥999”,两个无效等价类是“项数<1”或者“项数>999”。
②如果输入条件规定了输入值的集合,或者是规定了“必须如何”的条件,这时可确立一个有效等价类和一个无效等价类。例如,在Pascal语言中对变量标识符规定为“字母打头的……串”。那么所有以字母打头的构成有效等价类,而不在此集合内(不以字母打头)的归于无效等价类。
③如果输入条件是一个布尔量,则可以确定一个有效等价类和一个无效等价类。
④如果规定了输入数据的一组值,而且程序要对每个输入值分别进行处理。这时可为每一个输入值确立一个有效等价类,此外,针对这组值确立一个无效等价类,它是所有不允许的输入值的集合。例如,在教师分房方案中规定对教授、副教授、讲师和助教分别计算分数,做相应的处理,因此可以确定4个有效等价类为教授、副教授、讲师和助教,以及一个无效等价类,它是所有不符合以上身份的人员的输入值的集合。
⑤如果规定了输入数据必须遵守的规则,则可以确立一个有效等价类(符合规则)和若干个无效等价类(从不同角度违反规则)。例如,Pascal语言处理时规定“一个语句必须以分号‘;’结束”。这时,可以确定一个有效等价类“以‘;’结束”,若干个无效等价类“以‘:’结束”、“以‘,’结束”、“以‘’结束”等等。
⑥如果确知,已划分的等价类中各元素在程序中处理方式不同,则应将此等价类进一步划分成更小的等价类。
(2)确立测试用例
在确立了等价类之后,建立等价类表,列出所有划分出的等价类:
再从划分出的等价类中按以下原则选择测试用例:
①为每一个等价类规定一个唯一的编号;
②设计一个新的测试用例,使其尽可能多地覆盖尚未被覆盖的有效等价类,重复这一步,直到所有的有效等价类都被覆盖为止;
③设计一个新的测试用例,使其仅覆盖一个尚未被覆盖的无效等价类,直到所有的无效等价类都被覆盖为止。之所以要这样做,是因为某些程序中对某一输入错误的检查往往会屏蔽对其他输入错误的松果。因此必须针对每一个无效等价类,分别设计测试用例。
边界值分析也是一种黑盒测试方法,是对等价类划分方法的补充。使用边界值分析方法设计测试用例,首先应确定边界情况。通常输入等价类与输出等价类的边界,就是应着重测试边界情况。应当选取正好等于,刚刚大于,或刚刚小于边界的值作为测试数据,而不是选取等价类中的典型值或任意值作为测试数据。边界值分析方法选择测试用例的原则在很多方面与等价类划分方法类似。选择测试用例的原则:
⑴如果输入条件规定了值的范围,则应取刚达到这个范围的边界的值,以及刚刚超越这个范围边界的值作为测试输入数据。例如,若输入值的范围是“-1.0-1.0”,则可选取“-1.0”,“1.0”,“-1.001”,“1.001”作为测试输入数据。
⑵如果输入条件规定了值的个数,则用最大个数、最小个数、比最大个数多1、比最小个数少1的数作为测试数据。例如,一个输入文件可有1-255个记录,则可以分别设计有1个记录、255个记录以及0个记录和256个记录的输入文件。
⑶根据规格说明的每个输出条件,使用前面的原则⑴。例如某程序的功能是计算折扣量,最低折扣量是0元,最高折扣量是1050元。则设计一些测试用例,使它们恰好产生0元和1050元的结果。此外,还可考虑设计结果为负值或大于1050元的测试用例。
⑷根据规格说明的每个输出条件,使用前面的原则⑵。例如,一个信息检索系统根据用户打入的命令,显示有关文献的摘要,但最多只显示4篇摘要。这时可设计一些测试用例,使得程序分别显示1篇,4篇,0篇,并设计一个有可能使程序错误地显示5篇摘要的测试用例。
⑸如果程序的规格说明给出的输入域或输出域是有序集合(如有序表,顺序文件等),则应选取集合的第一个元素和最后一个元素作为测试用例。
⑹如果程序中使用了一个内部数据结构,则应当选择这个内部数据结构的边界上的值作为测试用例。例如,如果程序中定义了一个数组,其元素下标的下界是0,上界是100,那么应选择达到这个数组下标的值,如0与100,作为测试用例。
⑺分析规格说明,找出其他可能的边界条件
错误推测法的基本想法是:列举出程序中所有可能有的错误和容易发生错误的特殊情况。根据它们选择测试用例。
⑴等价类划分方法和边界值分析方法都是着重考虑输入条件,但未考虑输入条件之间的联系。如果在测试时必须考虑输入条件的各种组合,可能又会产生一些新的情况。要检查输入条件的组合不是一件容易的事情,即使把所有输入条件划分成等价类,它们间的组合情况也相当多。因此必须考虑使用一种适合于描述对于多种条件的组合,相应产生多个动作的形式来考虑设计测试用例,这就需要利用因果图。因果图方法最终生成的就是判定表。它适合于检查程序输入条件的各种组合情况。
⑵用因果图生成测试用例的基本步骤:
①分析软件规格说明描述中,哪些是原因(即输入条件或输入条件的等价类),哪些是结果(即输出条件),并给每个原因和结果赋予一个标识符。
②分析软件规格说明描述中的语义,找出原因与结果之间,在原因与原因之间对应的关系,根据这些关系,画出因果图。
③由于语法或环境限制,有些原因与原因之间,原因与结果之间的组合情况不可能出现。为表现这些特殊情况,在因果图上用一些记号标明约束或限制条件。
④把因果图转换成判定表。
⑤把判定表的每一列拿出来作为依据,设计测试用例。
⑶在因果图中出现的基本符号
通常在因果图中用Ci表示原因,用Ei表示结果。各结点表示状态,可取值“0”或“1”。“0”表示某状态不出现,“1”表示某状态出现。
①恒等:表示原因与结果之间一对一的对应关系。若原因出现,则结果出现。若原因不出现,则结果也不出现。
②非:表示原因与结果之间的一种否定关系。若原因出现,则结果不出现。若原因不出现,反而结果出现。
③或(∨):表示若几个原因中有一个出现,则结果出现,只有当这几个原因都不出现时,结果才不出现。
④与(∧):表示若几个原因都出现,结果才出现。若几个原因中有一个不出现,结果就不出现。
⑷表示约束条件的符号
①E(互斥):表示a,b两个原因不会同时成立,两个中最多一个可能成立。
②I(包含):表示a,b,c三个原因中至少有一个必须成立。
③O(唯一):表示a和b当中必须有一个,且仅有一个成立。
④R(要求):表示当a出现时,b必须也出现,不可能a出现,b不出现。
若从输出(结果)考虑,还有一种约束:
⑤M(屏蔽):表示当a是1时,b必须是0。而当a 为0时,b的值不定。
功能图方法是一种黑盒测试方法。它用功能图FD(Functional Diagram)形式化地表示程序的功能说明,并机械地生成功能图的测试用例。
功能图模型由状态迁移图和逻辑功能模型构成,状态迁移图用于表示输入数据序列以及相应的输出数据,在状态迁移图中,由输入数据和当前状态决定输出数据和后续状态。逻辑功能模型用于表示在状态中输入条件与输出条件之间的对应关系。
各省软考办 | ||||||||||