免费智能真题库 > 历年试卷 > 软件评测师 > 2009年上半年 软件评测师 上午试卷 综合知识
  第55题      
  知识点:   白盒测试   测试用例设计方法   逻辑覆盖法   用例设计   白盒测试的测试用例设计   测试用例设计
  关键词:   白盒测试   测试用例   白盒   测试   用例        章/节:   测试技术的分类       

 
关于白盒测试测试用例设计方法叙述,正确的是(55)。
 
 
  A.  完成SC (语句判定)所需的测试用例数目一定多于完成DC (逻辑判定)所需的测试用例数目
 
  B.  达到100%CC (条件判定)要求就一定能够满足100%SC的要求
 
  C.  达到100%CDC (条件判定组合覆盖)要求就一定能够满足100%CC的要求
 
  D.  任何情况下,都可以达到100%路径覆盖的要求
 
 
 

 
  第61题    2016年下半年  
   35%
一个程序的控制流图中有6个节点,10条边,在测试用例数最少的情况下,确保程序中每个可执行语句至少执行一次所需要的测试用例数的..
  第61题    2012年下半年  
   38%
逻辑覆盖标准包括(61)。
①判定覆盖
②语句覆盖
③条件判定覆盖
④修正条件判定覆盖
  第22题    2021年下半年  
   38%
良好的编程习惯不包括()。
   知识点讲解    
   · 白盒测试    · 测试用例设计方法    · 逻辑覆盖法    · 用例设计    · 白盒测试的测试用例设计    · 测试用例设计
 
       白盒测试
        白盒测试也称结构测试或逻辑驱动测试,它是按照程序内部的结构测试程序,通过测试来检测产品内部动作是否按照设计规格说明书的规定正常进行,检验程序中的每条通路是否都能按预定要求正确工作。
        这一方法是把测试对象看作一个打开的盒子,测试人员依据程序内部逻辑结构相关信息,设计或选择测试用例,对程序所有逻辑路径进行测试,通过在不同点检查程序的状态,确定实际的状态是否与预期的状态一致。
        采用什么方法对软件进行测试呢?常用的软件测试方法有两大类:静态测试方法和动态测试方法。其中软件的静态测试不要求在计算机上实际执行所测程序,主要以一些人工的模拟技术对软件进行分析和测试;而软件的动态测试是通过输入一组预先按照一定的测试准则构造的实例数据来动态运行程序,而达到发现程序错误的过程。这两种测试方法和相应测试用例的设计方法将在相应章节作详细介绍。
 
       测试用例设计方法
        初涉软件测试者可能认为拿到软件后就可以立即进行测试,并希望马上找出软件的所有缺陷,这种想法就如同没有受过工程训练的开发工程师急于去编写代码一样。软件测试也是一个工程,也需要按照工程的角度去认识软件测试,在具体的测试实施之前,我们需要明白我们测试什么,怎么测试等,也就是说通过制定测试用例指导测试的实施。
               什么是测试用例
               所谓的测试用例设计就是将软件测试的行为活动,作一个科学化的组织归纳。软件测试是有组织性、步骤性和计划性的,而设计软件测试用例的目的,就是为了能将软件测试的行为转换为可管理的模式。软件测试是软件质量管理中最实际的行动,同时也是耗时最多的一项。基于时间因素的考虑,软件测试行为必须能够加以量化,才能进一步让管理阶层掌握所需要的测试过程,而测试用例就是将测试行为具体量化的方法之一。
               简单地说,测试用例就是设计一个情况,软件程序在这种情况下,必须能够正常运行并且达到程序所设计的执行结果。如果程序在这种情况下不能正常运行,而且这种问题会重复发生,那就表示软件程序人员已经测出软件有缺陷,这时候就必须将这个问题标示出来,并且输入到问题跟踪系统内,通知软件开发人员。软件开发人员接获通知后,将这个问题修改完成于下一个测试版本内,软件测试工程师取得新的测试版本后,必须利用同一个用例来测试这个问题,确保该问题已修改完成。
               因为我们不可能进行穷举测试,为了节省时间和资源、提高测试效率,必须要从数量极大的可用测试数据中精心挑选出具有代表性或特殊性的测试数据来进行测试。
               使用测试用例的好处主要体现在以下几个方面。
               ①在开始实施测试之前设计好测试用例,可以避免盲目测试并提高测试效率。
               ②测试用例的使用令软件测试的实施重点突出、目的明确。
               ③在软件版本更新后只需修正少部分的测试用例便可展开测试工作,降低工作强度,缩短项目周期。
               ④功能模块的通用化和复用化使软件易于开发,而测试用例的通用化和复用化则会使软件测试易于开展,并随着测试用例的不断精化其效率也不断攀升。
               具体的黑盒测试用例设计方法包括等价类划分法、边界值分析法、错误推测法、因果图法、判定表驱动法、正交试验设计法、功能图法等。应该说,这些方法是比较实用的,但采用什么方法,在使用时自然要针对开发项目的特点对方法加以适当的选择。下面我们讨论几种常用的方法。
               等价类划分法
               等价类划分是一种典型的黑盒测试方法,用这一方法设计测试用例完全不考虑程序的内部结构,只根据对程序的要求和说明,即需求规格说明书。我们必须仔细分析和推敲说明书的各项需求,特别是功能需求。把说明中对输入的要求和输出的要求区别开来并加以分解。
               由于穷举测试工作量太大,以至于无法实际完成,促使我们在大量的可能数据中选取其中的一部分作为测试用例。例如,在不了解等价分配技术的前提下,我们做计算器程序的加法测试时,测试了1+1,1+2,1+3和1+4之后,还有必要测试1+5和1+6吗,能否放心地认为它们是正确的?我们感觉1+5和1+6,与前面的1+1,1+2都是很类似的简单加法。
               等价类划分的办法是把程序的输入域划分成若干部分,然后从每个部分中选取少数代表性数据作为测试用例。每一类的代表性数据在测试中的作用等价于这一类中的其他值,也就是说,如果某一类中的一个例子发现了错误,这一等价类中的其他例子也能发现同样的错误;反之,如果某一类中的一个例子没有发现错误,则这一类中的其他例子也不会查出错误(除非等价类中的某些例子属于另一等价类,因为几个等价类是可能相交的)。使用这一方法设计测试用例,首先必须在分析需求规格说明的基础上划分等价类,列出等价类表。
                      划分等价类和列出等价类表
                      等价类是指某个输入域的子集合。在该子集合中,各个输入数据对于揭露程序中的错误都是等效的。并合理地假定:测试某等价类的代表值就等于对这一类其他值的测试。
                      因此,可以把全部输入数据合理地划分为若干等价类,在每一个等价类中取一个数据作为测试的输入条件,就可以用少量代表性的测试数据取得较好的测试结果。等价类划分有两种不同的情况:有效等价类和无效等价类。
                      有效等价类:指对于程序的规格说明来说是合理的、有意义的输入数据构成的集合。利用有效等价类可检验程序是否实现了规格说明中所规定的功能和性能。
                      无效等价类:与有效等价类的定义恰巧相反。
                      设计测试用例时,要同时考虑这两种等价类。因为软件不仅要能接收合理的数据,也要能经受意外的考验。这样的测试才能确保软件具有更高的可靠性。
                      下面给出6条确定等价类的原则:
                      ①在输入条件规定了取值范围或值的个数的情况下,可以确立一个有效等价类和两个无效等价类。
                      ②在输入条件规定了输入值的集合或者规定了“必须如何”的条件的情况下,可以确立一个有效等价类和一个无效等价类。
                      ③在输入条件是一个布尔量的情况下,可确定一个有效等价类和一个无效等价类。
                      ④在规定了输入数据的一组值(假定n个),并且程序要对每一个输入值分别处理的情况下,可确立n个有效等价类和一个无效等价类。
                      ⑤在规定了输入数据必须遵守的规则的情况下,可确立一个有效等价类(符合规则)和若干个无效等价类(从不同角度违反规则)。
                      ⑥在确知已划分的等价类中,各元素在程序处理中的方式不同的情况下,则应再将该等价类进一步地划分为更小的等价类。
                      在确立了等价类之后,建立等价类表,列出所有划分出的等价类如下表所示。
                      
                      等价类表示例
                      确定测试用例
                      根据已列出的等价类表,按以下步骤确定测试用例:
                      ①为每个等价类规定一个惟一的编号。
                      ②设计一个新的测试用例,使其尽可能多地覆盖尚未覆盖的有效等价类。重复这一步,最后使得所有有效等价类均被测试用例所覆盖。
                      ③设计一个新的测试用例,使其只覆盖一个无效等价类。重复这一步使所有无效等价类均被覆盖。
                      在寻找等价区间时,想办法把软件的相似输入、输出、操作分成组。这些组就是等价区间。请看一些例子。
                      在两数相加用例中,测试1+13和1+99999999似乎有点不同。这是一种直觉,一个是普通加法,而另一个似乎有些特殊,这个直觉是对的。程序对1和最大数值相加的处理和对两个小一些的数值相加的处理有所不同。后者必须处理溢出情况。因为软件操作可能不同,所以这两个用例属于不同的等价区间。
                      如果具有编程经验,就可能会想到更多可能导致软件操作不同的“特殊”数值。如果不是程序员,也不用担心,你很快就会学到这种技术,无须了解代码细节就可以运用。
                      如下图所示是复制的多种方法,给出了选中编辑菜单后显示复制和粘贴命令的计算器程序。每一项功能(即复制和粘贴)有5种执行方式。要想复制,可以单击复制菜单命令,键入C,按Ctrl+C或Ctrl+Shift+C组合键。任何一种输入途径都会把当前数值复制到剪贴板中,一一执行同样的输出操作,产生同样的结果。
                      
                      复制的多种方法
                      如果要测试复制命令,可以把这5种输入途径划分减为3个,单击菜单命令,键入C和按Ctrl+C组合键。对软件质量有了信心之后,知道无论以何种方式激活复制功能都工作正常,甚至可以进一步缩减为1个区间,例如按Ctrl+C组合键。
                      再看下一个例子。看一下在标准的另存为对话框(如下图所示)中输入文件名称的情形。
                      
                      存盘对话框
                      Windows文件名可以包含除了“、”、“/”、“:”、“.”、“?”、“<>”和“\”之外的任意字符。文件名长度是1~255个字符。如果为文件名创建测试用例,等价区间有合法字符、非法字符、合法长度的名称、过长名称和过短名称。
                      例题:根据下面给出的规格说明,利用等价类划分的方法,给出足够的测试用例。“一个程序读入3个整数,把这3个数值看作一个三角形的3条边的长度值。这个程序要打印出信息,说明这个三角形是不等边的、是等腰的、还是等边的”。
                      我们可以设三角形的3条边分别为A, B, C。如果它们能够构成三角形的3条边,必须满足:
                      A>0,B>0,C>0,且A+B>C, B+C>A, A+C>B。
                      如果是等腰的,还要判断A=B,或B=C,或A=C。
                      如果是等边的,则需判断是否A=B,且B=C,且A=C。
                      列出等价类表,如下表所示。
                      
                      等价类表
                      设计测试用例:输入顺序是【A, B, C】,如下表所示。
                      
                      测试用例
                      请记住,等价分配的目标是把可能的测试用例组合缩减到仍然足以满足软件测试需求为止。因为,选择了不完全测试,就要冒一定的风险,所以必须仔细选择分类。
                      关于等价分配最后要讲的一点是,这样做有可能不客观。科学有时也是一门艺术。测试同一个复杂程序的两个软件测试员,可能会制定出两组不同的等价区间。只要审查等价区间的人都认为它们足以覆盖测试对象就可以了。
               边界值分析法
               人们从长期的测试工作经验得知,大量的错误是发生在输入或输出范围的边界上的,而不是在输入范围的内部。因此针对各种边界情况设计测试用例,可以查出更多的错误。例如,在做三角形计算时,要输入三角形的3个边长A、B和C。这3个数值应当满足A>0、B>0、C>0、A+B>C、A+C>B、B+C>A,才能构成三角形。但如果把6个不等式中的任何一个大于号“>”错写成大于等于号“≥”,那就不能构成三角形。问题恰恰出现在容易被疏忽的边界附近。这里所说的边界是指相当于输入等价类和输出等价类而言,稍高于其边界值及稍低于其边界值的一些特定情况。
                      边界条件
                      我们可以想象一下,如果在悬崖峭壁边可以自信地安全行走,平地就不在话下了。如果软件在能力达到极限时能够运行,那么在正常情况下一般也就不会有什么问题。
                      边界条件是特殊情况,因为编程从根本上说不怀疑边界有问题。奇怪的是,程序在处理大量中间数值时都是对的,但是可能在边界处出现错误。下面的一段源代码说明了在一个极简单的程序中是如何产生边界条件问题的。
                      
                      这段代码的意图是创建包含10个元素的数组,并为数组中的每一个元素赋初值-1。看起来相当简单。它建立了包含10个整数的数组data和一个计数值i。For循环是从1~10,数组中从第1个元素到第10个元素被赋予数值-1。那么边界问题在哪儿呢?
                      在大多数开发语言脚本中,应当以声明的范围定义数组,在本例中定义语句是dim data(10)as interger,第一个创建的元素是data(0),而不是data(1)。该程序实际上创建了一个从data(0)~data(10)共11个元素的数组。程序从1~10循环将数组元素的值初始化为-1,但是由于数组的第一个元素是data(0),因此它没有被初始化。程序执行完毕,数组值如下:
                      
                      注意data(0)的值是0,而不是-1。如果这位程序员以后忘记了,或者其他程序员不知道这个数据数组是如何初始化的,那么他就可能会用到数组的第1个元素data(0),以为它的值是-1。诸如此类的问题很常见,在复杂的大型软件中,可能导致极其严重的软件缺陷。
                      次边界条件
                      上面讨论的普通边界条件是最容易找到的。它们在产品说明书中有定义,或者在使用软件的过程中确定。而有些边界在软件内部,最终用户几乎看不到,但是软件测试仍有必要检查。这样的边界条件称为次边界条件或者内部边界条件。
                      寻找这样的边界不要求软件测试员具有程序员那样阅读源代码的能力,但是要求大体了解软件的工作方式。2的乘方和ASCII表就是这样的例子。
                             2的乘方
                             计算机和软件的计数基础是二进制数,用位(bit)来表示0和1,一个字节(byte)由8位组成,一个字(word)由两个字节组成等。下表中列出了常用的2的乘方单位及其范围或值。
                             
                             软件中2的乘方
                             上表中所列的范围和值是作为边界条件的重要数据。除非软件向用户提出这些范围,否则在需求文档中不会指明。然而,它们通常由软件内部使用,外部是看不见的,当然,在产生软件缺陷的情况下可能会看到。
                             在建立等价区间时,要考虑是否需要包含2的乘方边界条件。例如,如果软件接受用户输入1~1000范围内的数字,谁都知道在合法区间中包含1和1000,也许还要有2和999。为了覆盖任何可能的2的乘方次边界,还要包含临近双位边界的14、15和16,以及临近字节边界的254、255和256。
                             ASCII表
                             另一个常见的次边界条件是ASCII字符表。如下表所示是部分ASCII值表的清单。
                             
                             部分ASCII值表
                             注意,上表不是结构良好的连续表。0~9的后面ASCII值是48~57。斜杠字符(/)在数字0的前面,而冒号字符“:”在数字9的后面。大写字母A~Z对应65~90。小写字母对应97~122。这些情况都代表次边界条件。
                             如果测试进行文本输入或文本转换的软件,在定义数据区间包含哪些值时,参考一下ASCII表是相当明智的。例如,如果测试的文本框只接受用户输入字符A~Z和a~z,就应该在非法区间中包含ASCII表中这些字符前后的值@、[、和{。
                             其他一些边界条件
                             另一种看起来很明显的软件缺陷来源是当软件要求输入时(比如在文本框中),不是没有输入正确的信息,而是根本没有输入任何内容,只按了Enter键。这种情况在产品说明书中常常被忽视,程序员也可能经常遗忘,但是在实际使用中却时有发生。程序员总会习惯性地认为用户要么输入信息,不管是看起来合法的或非法的信息,要么就会选择Cancel键放弃输入,如果没有对空值进行好的处理的话,恐怕程序员自己都不知道程序会引向何方。
                             正确的软件通常应该将输入内容默认为合法边界内的最小值,或者合法区间内的某个合理值,否则,返回错误提示信息。
                             因为这些值通常在软件中进行特殊处理,所以不要把它们与合法情况和非法情况混在一起,而要建立单独的等价区间。
                      边界值的选择方法
                      边界值分析是一种补充等价划分的测试用例设计技术,它不是选择等价类的任意元素,而是选择等价类边界的测试用例。实践证明,为检验边界附近的处理专门设计测试用例,常常取得良好的测试效果。边界值分析法不仅重视输入条件边界,而且也适用于输出域测试用例。
                      对边界值设计测试用例,应遵循以下几条原则:
                      ①如果输入条件规定了值的范围,则应取刚达到这个范围的边界的值,以及刚刚超越这个范围边界的值作为测试输入数据。
                      ②如果输入条件规定了值的个数,则用最大个数、最小个数、比最小个数少1、比最大个数多1的数作为测试数据。
                      ③根据规格说明的每个输出条件,使用前面的原则①。
                      ④根据规格说明的每个输出条件,应用前面的原则②。
                      ⑤如果程序的规格说明给出的输入域或输出域是有序集合,则应选取集合的第一个元素和最后一个元素作为测试用例。
                      ⑥如果程序中使用了一个内部数据结构,则应当选择这个内部数据结构边界上的值作为测试用例。
                      ⑦分析规格说明,找出其他可能的边界条件。
               错误推测法
               错误推测法就是基于经验和直觉推测程序中所有可能存在的各种错误,有针对性地设计测试用例的方法。
               错误推测法的基本思想是列举出程序中所有可能有的错误和容易发生错误的特殊情况,根据它们选择测试用例。例如,设计一些非法、错误、不正确和垃圾数据进行输入测试是很有意义的。如果软件要求输入数字,就输入字母。如果软件只接受正数,就输入负数。如果软件对时间敏感,就看它在公元3000年是否还能正常工作。还有,例如,在单元测试时曾列出的许多在模块中常见的错误,以前产品测试中曾经发现的错误等,这些就是经验的总结。另外,输入数据和输出数据为0的情况,或者输入表格为空格或输入表格只有一行,这些都是容易发生错误的情况。可选择这些情况下的例子作为测试用例。
               因果图法
               前节介绍的等价类划分方法和边界值分析法都是着重考虑输入条件,并没有考虑到输入情况的各种组合,也没考虑到各个输入情况之间的相互制约关系。如果在测试时必须考虑输入条件的各种组合,可能的组合数将是天文数字。因此必须考虑描述多种条件的组合,相应地产生多个动作的形式来考虑设计测试用例,这就需要利用因果图。在软件工程中,有些程序的功能可以用判定表的形式来表示,并根据输入条件的组合情况规定相应的操作。很自然,应该为判定表中的每一列设计一个测试用例,以便保证测试程序在输入条件的某种组合下,操作是正确的。
                      因果图设计方法
                      因果图法是从用自然语言书写的程序规格说明的描述中找出因(输入条件)和果(输出或程序状态的改变),通过因果图转换为判定表。
                      利用因果图导出测试用例需要经过以下几个步骤:
                      ①分析程序规格说明的描述中,哪些是原因,哪些是结果。原因常常是输入条件或是输入条件的等价类,而结果是输出条件。
                      ②分析程序规格说明的描述中语义的内容,并将其表示成连接各个原因与各个结果的“因果图”。
                      ③标明约束条件。由于语法或环境的限制,有些原因和结果的组合情况是不可能出现的。为表明这些特定的情况,在因果图上使用若干个标准的符号标明约束条件。
                      ④把因果图转换成判定表。
                      ⑤为判定表中每一列表示的情况设计测试用例。
                      因果图生成的测试用例(局部,组合关系下的)包括了所有输入数据的取TRUE与取FALSE的情况,构成的测试用例数目达到最少,且测试用例数目随输入数据数目的增加而增加。
                      事实上,在较为复杂的问题中,这个方法常常是十分有效的,它能有力地帮助我们确定测试用例。当然,如果哪个开发项目在设计阶段就采用了判定表,也就不必再画因果图了,而是可以直接利用判定表设计测试用例了。
                      通常在因果图中,用Ci表示原因,Ei表示结果,其基本符号如下图所示。各结点表示状态,可取“0”或“1”值。“0”表示某状态不出现,“1”表示某状态出现。
                      
                      因果图的基本图形符号
                      ①恒等:若原因出现,则结果出现;若原因不出现,则结果也不出现。
                      ②非(~):若原因出现,则结果不出现;若原因不出现,则结果出现。
                      ③或(∨):若几个原因中有1个出现,则结果出现;若几个原因都不出现,则结果不出现。
                      ④与(∧):若几个原因都出现,结果才出现。若其中有1个原因不出现,则结果不出现。
                      为了表示原因与原因之间、结果与结果之间可能存在的约束条件,在因果图中可以附加一些表示约束条件的符号。从输入(原因)考虑,有4种约束,例如:(a)、(b)、(c)、(d)。从输出(结果)考虑,还有1种约束,例如:(e),如下图所示。
                      
                      因果图的约束符号
                      ①E(互斥):表示a、b两个原因不会同时成立,两个中最多有一个可能成立。
                      ②I(包含):表示a、b、c这3个原因中至少有一个必须成立。
                      ③O(惟一):表示a和b当中必须有一个,且仅有一个成立。
                      ④R(要求):表示当a出现时,b必须也出现。a出现时不可能b不出现。
                      ⑤M(屏蔽):表示当a是1时,b必须是0。而当a为0时,b的值不定。
                      因果图测试用例
                      例如:有一个处理单价为1元5角钱的盒装饮料的自动售货机软件。若投入1元5角硬币,按下“可乐”、“雪碧”或“红茶”按钮,相应的饮料就送出来。若投入的是两元硬币,在送出饮料的同时退还5角硬币。
                      分析这一段说明,我们可以列出原因和结果。
                      原因:①投入1元5角硬币;②投入2元硬币;
                      ③按“可乐”按钮;④按“雪碧”按钮;⑤按“红茶”按钮。
                      中间状态:①已投币;②已按钮。
                      结果:①退还5角硬币;②送出“可乐”饮料;
                      ③送出“雪碧”饮料;④送出“红茶”饮料。
                      根据原因和结果,我们可以设计这样一个因果图(如下图所示。)
                      
                      因果图
                      转换为测试用例,如下表所示,每一列可作为确定测试用例的依据。
                      
                      5-6
               判定表驱动法
               前面因果图方法中已经用到了判定表。判定表是分析和表达多逻辑条件下执行不同操作的情况的工具。在程序设计发展的初期,判定表就已被用作编写程序的辅助工具了。它可以把复杂的逻辑关系和多种条件组合的情况表达得较明确。
                      判定表组成
                      判定表通常由4个部分组成,如下图所示。
                      
                      判定表
                      . 条件桩(condition stub):列出了问题的所有条件。通常认为列出的条件的次序无关紧要。
                      . 动作桩(action stub):列出了问题规定可能采取的操作。这些操作的排列顺序没有约束。
                      . 条件项(condition entry):列出针对它所列条件的取值,在所有可能情况下的真假值。
                      . 动作项(action entry):列出在条件项的各种取值情况下应该采取的动作。
                      . 规则:任何一个条件组合的特定取值及其相应要执行的操作。在判定表中贯穿条件项和动作项的一列就是一条规则。显然,判定表中列出多少组条件取值,也就有多少条规则,条件项和动作项就有多少列。
                      判定表建立
                      判定表的建立因该依据软件规格说明,步骤如下:
                      ①确定规则的个数。假如有n个条件,每个条件有两个取值(0,1),故有2n种规则。
                      ②列出所有的条件桩和动作桩。
                      ③填入条件项。
                      ④填入动作项。制定初始判定表。
                      ⑤简化。合并相似规则或者相同动作。
                      Beizer指出了适合使用判定表设计测试用例的条件:
                      ①规格说明以判定表的形式给出,或很容易转换成判定表。
                      ②条件的排列顺序不影响执行哪些操作。
                      ③规则的排列顺序不影响执行哪些操作。
                      ④当某一规则的条件已经满足,并确定要执行的操作后,不必检验别的规则。
                      ⑤如果某一规则要执行多个操作,这些操作的执行顺序无关紧要。
               正交试验法
               利用因果图来设计测试用例时,作为输入条件的原因与输出结果之间的因果关系,有时很难从软件需求规格说明中得到。往往因果关系非常庞大,导致利用因果图而得到的测试用例数目多得惊人,给软件测试带来沉重的负担。为了有效地、合理地减少测试的工时与费用,可利用正交试验法进行测试用例的设计。
                      正交试验设计方法
                      依据Galois理论,正交试验设计方法是从大量的试验数据中挑选适量的、有代表性的点,从而合理地安排测试的一种科学的试验设计方法。
                      正交试验法,就是使用已经造好了的表格“——”正交表来安排试验并进行数据分析的一种方法。它简单易行并且计算表格化,应用性较好。下边通过一个例子来说明正交试验法。
                      例题:为提高某化工产品的转化率,选择了三个有关因素进行条件试验,反应温度(A),反应时间(B),用碱量(C),并确定了它们的试验范围如下。
                      . A:80~90℃;
                      . B:90~150分钟;
                      . C:5%~7%。
                      试验目的是搞清楚因子A、B、C对转化率有什么影响,哪些是主要的,哪些是次要的,从而确定最适生产条件,即温度、时间及用碱量各为多少才能使转化率最高。这里,对因子A、B和C,在试验范围内都选了三个水平,如下所示。
                      . A:A1=80℃,A2=85℃,A3=90℃;
                      . B:B1=90分钟,B2=120分钟,B3=150分钟;
                      . C:C1=5%,C2=6%,C3=7%。
                      当然,在正交试验设计中,因子可以是定量的,也可以是定性的。而定量因子各水平间的距离可以相等,也可以不相等。这个三因子三水平的条件试验,通常有两种试验方法:
                      ①取三因子所有水平之间的组合,即A1B1C1,A1B1C2,A1B2C1,……,A3B3C3,共有33=27次试验。用下图表示立方体的27个节点。这种试验法叫做全面试验法。
                      
                      全面试验法取点
                      全面试验对各因子与指标间的关系剖析得比较清楚。但试验次数太多。特别是当因子数目多,每个因子的水平数目也很多时,试验量非常大。如选6个因子,每个因子取5个水平时,如欲做全面试验,则需56=15625次试验,这实际上是不可能实现的。如果应用将要介绍的正交试验法,只做25次试验就行了。而且在某种意义上讲,这25次试验代表了15625次试验。
                      ②简单对比法,即变化一个因素而固定其他因素,如首先固定B、C于Bl、Cl,使A变化:
                      
                      如得出结果A3最好,则固定A于A3,C还是Cl,使B变化:
                      
                      得出结果以B2为最好,则固定B于B2,A于A3,使C变化:
                      
                      试验结果以C2为最好。于是就认为最好的工艺条件是A3B2C2。
                      这种方法一般也有一定的效果,但缺点很多。首先这种方法的选点代表性很差,如按上述方法进行试验,试验点完全分布在一个角上,而在一个很大的范围内没有选点,因此这种试验方法不全面,所选的工艺条件A3B2C2不一定是27个组合中最好的。其次,用这种方法比较条件好坏时,是把单个的试验数据拿来,进行数值上的简单比较,而试验数据中必然包含着误差成分,所以单个数据的简单比较不能剔除误差,必然造成结论的不稳定。
                      简单对比法的最大优点就是试验次数少,例如,6因子5水平试验,在不重复时,只用5+(6-1)×(5-1)=5+5×4=25次试验就可以了。
                      考虑兼顾这两种试验方法的优点,从全面试验的点中选择具有典型性、代表性的点,使试验点在试验范围内分布得很均匀,能反映全面情况。但我们又希望试验点尽量地少,为此还要具体考虑一些问题。如上例,对应于A有A1、A2、A3 3个平面,对应于B、C也各有3个平面,共9个平面。则这9个平面上的试验点都应当一样多,即对每个因子的每个水平都要同等看待。具体来说,每个平面上都有3行、3列,要求在每行、每列上的点一样多。这样,作出如下图所示的设计,试验点用⊙表示。我们看到,在9个平面中每个平面上都恰好有3个点,而每个平面的每行每列都有1个点,而且只有1个点,总共9个点。这样的试验方案,试验点的分布很均匀,试验次数也不多。
                      
                      正交试验设计图例
                      当因子数和水平数都不太大时,尚可通过作图的办法来选择分布很均匀的试验点。但是因子数和水平数多了,作图的方法就不行了。试验工作者在长期的工作中总结出一套办法,创造出所谓的正交表。按照正交表来安排试验,既能使试验点分布得很均匀,又能减少试验次数,而且计算分析简单,能够清晰地阐明试验条件与指标之间的关系。用正交表来安排试验及分析试验结果,这种方法叫正交试验设计法。
                      一般用L代表正交表,常用的有L8(27)、L9(34)、L16(45)、L8(4×24)等。此符号各数字的意义如下。
                      例如:L8(27),其中,7为此表列的数目(最多可安排的因子数);2为因子的水平数;8为此表行的数目(试验次数)。
                      又例如:L18(2×37),有7列是3水平的,有1列是2水平的,L18(2×37)的数字告诉我们,用它来安排试验,做18个试验最多可以考察1个2水平因子和7个3水平因子。
                      在行数为mn型的正交表中(m, n是正整数),试验次数(行数)=Σ(每列水平数-1)+1,如L8(27),8=7×(2-1)+1,利用上述关系式可以从所要考察的因子水平数来决定最低的试验次数,进而选择合适的正交表。比如要考察5个3水平因子及一个2水平因子,则起码的试验次数为5×(3-1)+1×(2-1)+1=12(次),这就是说,要在行数不小于12,既有2水平列又有3水平列的正交表中选择,L18(2×37)适合。正交表具有两条性质:每一列中各数字出现的次数都一样多;任何两列所构成的各有序数对出现的次数都一样多。所以称之为正交表。
                      例如,在L9(34)中(如下表所示),各列中的1、2、3都各自出现3次;任何两列,例如第3、4列,所构成的有序数对从上向下共有9种,既没有重复也没有遗漏。其他任何两列所构成的有序数对也是这9种各出现一次。这反映了试验点分布的均匀性。
                      
                      L9(34)正交表
                      试验方案应该如何设计呢?安排试验时,只要把所考察的每一个因子任意地对应于正交表的一列(一个因子对应一列,不能让两个因子对应同一列),然后把每列的数字“翻译”成所对应因子的水平。这样,每一行的各水平组合就构成了一个试验条件(不考虑没安排因子的列)。对于上例,因子A、B、C都是3水平的,试验次数要不少于3×(3-1)+1=7(次),可考虑选用L9(34)。因子A、B、C可任意地对应于L9(34)的某三列,例如A、B、C分别放在1、2、3列,然后试验按行进行,顺序不限,每一行中各因素的水平组合就是每一次的试验条件,从上到下就是这个正交试验的方案,如下表所示。这个试验方案的几何解释正好是正交试验设计图例。
                      
                      试验方案
                      3个3水平的因子,做全面试验需要33=27次试验,现用L9(34)来设计试验方案,只要做9次,工作量减少了2/3,而在一定意义上代表了27次试验。
                      正交试验测试用例设计步骤
                      利用正交试验设计测试用例的步骤如下。
                      . 提取功能说明,构造因子“——”状态表。把影响实验指标的条件称为因子,而影响实验因子的条件叫做因子的状态。利用正交试验设计方法来设计测试用例时,首先要根据被测试软件的规格说明书找出影响其功能实现的操作对象和外部因素,把它们当作因子,而把各个因子的取值当做状态。对软件需求规格说明中的功能要求进行划分,把整体的、概要性的功能要求进行层层分解与展开,分解成具体的、有相对独立性的基本的功能要求。这样就可以把被测试软件中所有的因子都确定下来,并为确定因子的权值提供参考的依据。确定因子与状态是设计测试用例的关键。因此,要求尽可能全面地、正确地确定取值,以确保测试用例的设计做到完整与有效。
                      . 加权筛选,生成因素分析表。对因子与状态的选择可按其重要程度分别加权。可根据各个因子及状态作用的大小、出现频率的大小以及测试的需要,确定权值的大小。
                      . 利用正交表构造测试数据集,正交表的推导依据Galois理论。
                      利用正交试验设计方法设计测试用例,与使用等价类划分、边界值分析、因果图等方法相比,有以下优点:节省测试工作工时;可控制生成的测试用例的数量;测试用例具有一定的覆盖率。
                      正交试验法在软件测试中是一种有效的方法,例如在平台参数配置方面,我们要选择哪种组合方式是最好的,每个参数可能就是一个因子,参数的不同取值就是水平,这样我们可以采用正交试验法设计出最少的测试组合,达到有效的测试目的。
               功能图法
               一个程序的功能说明通常由动态说明和静态说明组成。动态说明描述了输入数据的次序或转移的次序。静态说明描述了输入条件与输出条件之间的对应关系。对于较复杂的程序,由于存在大量的组合情况,因此,仅用静态说明组成的规格说明对于测试来说往往是不够的,必须用动态说明来补充功能说明。
                      功能图设计方法
                      功能图方法是用功能图形象地表示程序的功能说明,并机械地生成功能图的测试用例。功能图模型由状态迁移图和逻辑功能模型构成。
                      . 状态迁移图用于表示输入数据序列以及相应的输出数据。在状态迁移图中,由输入数据和当前状态决定输出数据和后续状态。
                      . 逻辑功能模型用于表示在状态中输入条件和输出条件之间的对应关系。逻辑功能模型只适合于描述静态说明,输出数据仅由输入数据决定。测试用例则是由测试中经过的一系列状态和在每个状态中必须依靠输入/输出数据满足的一对条件组成。
                      功能图方法实际上是一种黑盒、白盒混合用例设计方法。
                      功能图方法中要用到逻辑覆盖和路径测试的概念和方法,属白盒测试方法中的内容。逻辑覆盖是以程序内部的逻辑结构为基础的测试用例设计方法,该方法要求测试人员对程序的逻辑结构有清楚的了解。由于覆盖测试的目标不同,逻辑覆盖可分为:语句覆盖、判定覆盖、判定-条件覆盖,条件组合覆盖及路径覆盖。下面我们指的逻辑覆盖和路径是功能或系统水平上的,以区别于白盒测试中的程序内部的,如下图及下表所示。
                      
                      功能图
                      
                      判定表
                      
                      功能图法生成测试用例
                      功能图由状态迁移图和布尔函数组成。状态迁移图用状态和迁移来描述一个状态,指出数据输入的位置(或时间),而迁移则指明状态的改变,同时要依靠判定表和因果图表示的逻辑功能。
                      采用什么样的方法生成测试用例?从功能图生成测试用例,得到的测试用例数是可接受的。问题的关键是如何从状态迁移图中选取测试用例。若用节点代替状态,用弧线代替迁移,状态迁移图就可转化成一个程序的控制流程图形式。问题就转化为程序的路径测试问题(白盒测试范畴概念)了。
                      测试用例生成规则:为了把状态迁移(测试路径)的测试用例与逻辑模型的测试用例组合起来,从功能图生成实用的测试用例,需定义下面的规则。一个结构化的状态迁移中,定义3种形式的循环:顺序、选择和重复。但分辨一个状态迁移中的所有循环是有困难的。
                      从功能图生成测试用例的过程如下。
                      . 生成局部测试用例:在每个状态中,从因果图生成局部测试用例。局部测试库由原因值(输入数据)组合与对应的结果值(输出数据或状态)构成。
                      . 测试路径生成:利用上面的规则生成从初始状态到最后状态的测试路径。
                      . 测试用例合成:合成测试路径与功能图中每个状态的局部测试用例。结果是视状态到最后状态的一个状态序列,以及每个状态中输入数据与对应输出数据组合。
                      . 测试用例的合成算法:采用条件构造树。
               场景法
               现在的软件几乎都是用事件触发来控制流程的,事件触发时的情景便形成了场景,而同一事件不同的触发顺序和处理结果就形成事件流。这种在软件设计方面的思想也可引入到软件测试中,可以比较生动地描绘出事件触发时的情景,有利于测试设计者设计测试用例,同时使测试用例更容易理解和执行。
               提出这种测试思想的是Rational公司,并在RUP2000中文版中有详尽的解释和应用。
               用例场景用来描述流经用例的路径,从用例开始到结束遍历这条路径上所有基本流和备选流。
                      基本流和备选流
                      如下图所示,图中经过用例的每条路径都用基本流和备选流来表示,直黑线表示基本流,是经过用例的最简单的路径。备选流用不同的彩色表示,一个备选流可能从基本流开始,在某个特定条件下执行,然后重新加入基本流中(如备选流1和3);也可能起源于另一个备选流(如备选流2),或者终止用例而不再重新加入到某个流(如备选流2和4)。
                      按照如下图中所示的每个经过用例的路径,可以确定以下不同的用例场景。
                      
                      基本流和备选流
                      场景1:基本流;
                      场景2:基本流、备选流1;
                      场景3:基本流、备选流1、备选流2;
                      场景4:基本流、备选流3;
                      场景5:基本流、备选流3、备选流1;
                      场景6:基本流、备选流3、备选流1、备选流2;
                      场景7:基本流、备选流4;
                      场景8:基本流、备选流3、备选流4。
                      注:为方便起见,场景5、6和8只考虑了备选流3循环执行一次的情况。
                      需要说明的是,为了能清晰地说明场景,我们所举的例子都非常简单,在实际应用中,测试用例很少如此简单。
                      ATM例子
                             例子描述
                             如下图所示是ATM例子的流程示意图。
                             
                             ATM流程示意图
                             如下表所示,包含了如上图中所示提款用例的基本流和某些备用流。
                             
                             用例流
                             
                             场景设计
                             如下表所示是生成的场景。
                             
                             场景设计
                             注:为方便起见,备选流3和6(场景3和7)内的循环以及循环组合未纳入表中。
                             用例设计
                             对于这7个场景中的每一个场景都需要确定测试用例,一般采用矩阵或决策表来确定和管理测试用例。如下表所示是一种通用格式,其中行代表各个测试用例,列代表测试用例的信息。本例中的测试用例包含测试用例ID、场景/条件、测试用例中涉及的所有数据元素和预期结果等项目。首先确定执行用例场景所需的数据元素,然后构建矩阵,最后要确定包含执行场景所需的适当条件的测试用例。在下面的矩阵中,V表示这个条件必须是有效的才可执行基本流,I表示这种条件下将激活所需备选流,n/a表示这个条件不适用于测试用例。
                             
                             测试用例表
                             在上面的矩阵中,六个测试用例执行了四个场景。对于基本流,上述测试用例CW1被称为正面测试用例。它一直沿着用例的基本流路径执行,未发生任何偏差。基本流的全面测试必须包括负面测试用例,以确保只有在符合条件的情况下才执行基本流。这些负面测试用例由CW2~CW6表示。虽然CW2~CW6相对于基本流而言都是负面测试用例,但它们相对于备选流2~4而言是正面测试用例。而且对于这些备选流中的每一个而言,至少存在一个负面测试用例,就是CW1-基本流。
                             每个场景只有一个正面测试用例和负面测试用例是不充分的,场景4正是这样的一个示例。要全面地测试场景4-PIN有误,至少需要三个正面测试用例,以激活场景4:
                             ①输入了错误的PIN,但仍存在输入机会,此备选流重新加入基本流中的步骤3-输入PIN。
                             ②输入了错误的PIN,而且不再有输入机会,则此备选流将保留银行卡并终止用例。
                             ③最后一次输入时输入了“正确”的PIN。备选流在步骤5-输入金额处重新加入基本流。
                             注意,在上面的矩阵中,无需为条件输入任何实际的值。以这种方式创建测试用例矩阵的一个优点在于容易看到测试的是什么条件。由于只需要查看V和I,这种方式还易于判断是否已经确定了充足的测试用例。从上表中可发现存在几个无效的条件I,这表明测试用例还不完全,如场景6-不存在的账户/账户类型有误和场景7-账户余额不足就缺少测试用例。
                             数据设计
                             一旦确定了所有的测试用例,则应对这些用例进行复审和验证以确保其准确且适度,并取消多余或等效的测试用例。
                             
                             测试数据表
                             测试用例一经认可,就可以确定实际数据值(在测试用例实施矩阵中)并且设定测试数据。
                             以上测试用例只是在本次迭代中需要用来验证提款用例的一部分测试用例。需要的其他测试用例包括以下内容。
                             场景6——账户不存在/账户类型有误:未找到账户或账户不可用;
                             场景6——账户不存在/账户类型有误:禁止从该账户中提款;
                             场景7——账户余额不足:请求的金额超出账面金额。
                             在将来的迭代中,当实施其他事件流时,在下列情况下将需要测试用例:
                             ①无效卡(所持卡为挂失卡、被盗卡、非承兑银行发卡、磁条损坏等);
                             ②无法读卡(读卡机堵塞、脱机或出现故障);
                             ③账户已消户、冻结或由于其他方面原因而无法使用;
                             ④ATM内的现金不足或不能提供所请求的金额(与CW3不同,在CW3中只是一种币值不足,而不是所有币值都不足);
                             ⑤无法联系银行系统以获得认可;
                             ⑥银行网络离线或交易过程中断电。
                             结论:所有从事软件测试和即将从事软件测试的人大都是从黑盒测试做起的,每种类型的软件有各自的特点,每种测试用例设计的方法也有各自的特点,针对不同软件如何利用这些黑盒方法是非常重要的,它能极大地提高测试效率和测试覆盖度,认真掌握这些方法的原理,有效提高测试水平,积累更多的测试经验,这是测试人员最宝贵的财富。
               测试方法选择的综合策略
               测试用例的设计方法不是单独存在的,具体到每个测试项目里都会用到多种方法,每种类型的软件有各自的特点,每种测试用例设计的方法也有各自的特点,针对不同软件如何利用这些黑盒方法是非常重要的,在实际测试中,往往是综合使用各种方法才能有效地提高测试效率和测试覆盖度,这就需要认真掌握这些方法的原理,积累更多的测试经验,以有效地提高测试水平。
               以下是各种测试方法选择的综合策略,可供读者在实际应用过程中参考。
               ①首先进行等价类划分,包括输入条件和输出条件的等价划分,将无限测试变成有限测试,这是减少工作量和提高测试效率最有效的方法。
               ②在任何情况下都必须使用边界值分析方法。经验表明,用这种方法设计出的测试用例发现程序错误的能力最强。
               ③可以用错误推测法追加一些测试用例,这需要依靠测试工程师的智慧和经验。
               ④对照程序逻辑,检查已设计出的测试用例的逻辑覆盖程度。如果没有达到要求的覆盖标准,应当再补充足够的测试用例。
               ⑤如果程序的功能说明中含有输入条件的组合情况,则一开始就可选用因果图法和判定表驱动法。
               ⑥对于参数配置类的软件,要用正交试验法选择较少的组合方式达到最佳效果。
               ⑦功能图法也是很好的测试用例设计方法,我们可以通过不同时期条件的有效性设计不同的测试数据。
               ⑧对于业务流清晰的系统,可以利用场景法贯穿整个测试案例过程,在案例中综合使用各种测试方法。
 
       逻辑覆盖法
        白盒测试的动态测试要根据程序的控制结构设计测试用例,其原则是:
        . 保证一个模块中的所有独立路径至少被使用一次;
        . 对所有逻辑值均需测试true和false;
        . 在上下边界及可操作范围内运行所有循环;
        . 检查内部数据结构以确保其有效性。
        但是对一个具有多重选择和循环嵌套的程序,不同的路径数目可能是天文数字。而且即使精确地实现了白盒测试,也不能断言测试过的程序完全正确。如下图所示的穷举测试流程图,其中包括了一个执行达20次的循环,它所包含的不同执行路径数高达520条,假使有这么一个测试程序,对每一条路径进行测试需要1ms,假设一天工作24小时,一年工作365天,若要对它进行穷举测试,也需要3024年的时间。
        
        穷举测试
        以上的情况说明,实现穷举测试的工作量过大,需要的时间过长,实施起来是不现实的。任何软件开发项目都要受到期限、费用、人力和机时等条件的限制,尽管我们以为为了充分揭露程序中的所有隐藏错误,彻底的做法是针对所有可能的数据进行测试,但事实告诉人们,这样做是不可能的。
        在测试阶段既然穷举测试不可行,为了节省时间和资源,提高测试效率,就必须精心设计测试用例,也就是从数量巨大的可用测试用例中精心挑选少量的测试数据,使得采用这些测试数据就能够达到最佳的测试效果。
        本节和下节将介绍几种实用的白盒测试用例设计方法:逻辑覆盖法和基本路径测试法。
        逻辑覆盖是通过对程序逻辑结构的遍历实现程序的覆盖。它是一系列测试过程的总称,这组测试过程逐渐进行越来越完整的通路测试。从覆盖源程序语句的详尽程度分析,逻辑覆盖标准包括以下不同的覆盖标准:语句覆盖(SC)、判定覆盖(DC)、条件覆盖(CC)、条件判定组合覆盖(CDC)、多条件覆盖(MCC)和修正判定条件覆盖(MCDC)。
        为便于理解,我们使用如下所示的程序(用C语言书写),如下图所示的是其流程图。
        [程序]:
        
        
        参考例子流程图
               语句覆盖(SC)
               为了暴露程序中的错误,程序中的每条语句至少应该执行一次。因此,语句覆盖(Statement Coverage)的含义是:选择足够多的测试数据,使被测程序中每条语句至少执行一次。
               为了使上述程序中的每条语句都能够至少执行一次,我们可以构造以下测试用例即可实现:
               a=T, b=T, c=T。
               从程序中的每条语句都得到执行这一点看,语句覆盖的方法似乎能够比较全面地检验每一条语句,但是语句覆盖对程序执行逻辑的覆盖很低,这是其最严重的缺陷。
               假如,这一程序段中判定的逻辑运算有问题,例如,判定的第一个运算符“&&”错写成运算符“||”,或第二个运算符“||”错写成运算符“&&”,这时使用上述的测试用例仍然可以达到100%的语句覆盖,上述的逻辑错误无法发现。
               因此一般认为语句覆盖是很弱的逻辑覆盖。
               判定覆盖(DC)
               比语句覆盖稍强的覆盖标准是判定覆盖(Decision Coverage)。判定覆盖的含义是:设计足够的测试用例,使得程序中的每个判定至少都获得一次“真值”或“假值”,或者说使得程序中的每一个取“真”分支和取“假”分支至少经历一次,因此判定覆盖又称为分支覆盖。
               除了双值的判定语句外,还有多值判定语句,如case语句,因此判定覆盖更一般的含义是:使得每一个判定获得每一种可能的结果至少一次。
               以上述代码为例,构造以下测试用例即可实现判定覆盖标准:
               . a=T, b=T, c=T。
               . a=F, b=F, c=F。
               应该注意到,上述两组测试用例不仅满足了判定覆盖,而且满足了语句覆盖,从这一点看,判定覆盖要比语句覆盖更强一些。但是同样地,假如这一程序段中判定的逻辑运算有问题,如下表所示,判定的第一个运算符“&&”错写成运算符“||”或第二个运算符“||”错写成运算符“&&”,这时使用上述的测试用例可以达到100%的判定覆盖,仍然无法发现上述的逻辑错误。因此需要更强的逻辑覆盖标准。
               
               判定覆盖
               条件覆盖(CC)
               在设计程序中,一个判定语句是由多个条件组合而成的复合判定,在如上图所示参考例子流程图的程序中,判定(a)AND(b OR c)包含了三个条件:a, b和c。为了更彻底地实现逻辑覆盖,可以采用条件覆盖(Condition Coverage)的标准。条件覆盖的含义是:构造一组测试用例,使得每一判定语句中每个逻辑条件的可能值至少满足一次。
               按照这一定义,上述例子要达到100%的条件覆盖,可以使用以下测试用例:
               . a=F, b=T, c=F。
               . a=T, b=F, c=T。
               仔细分析可以发现,上述用例在满足条件覆盖的同时,把判定的两个分支也覆盖了,这样是否可以说,达到了条件覆盖也就必然实现了判定覆盖呢?
               假如选用以下的两组测试用例:
               . a=F, b=T, c=T。
               . a=T, b=F, c=F。
               我们会发现覆盖了条件的测试用例并没有覆盖分支,如下表所示。为解决这一矛盾,需要对条件和分支兼顾。
               
               条件覆盖
               条件判定组合覆盖(CDC)
               条件判定组合覆盖的含义是:设计足够的测试用例,使得判定中每个条件的所有可能(真/假)至少出现一次,并且每个判定本身的判定结果(真/假)也至少出现一次。
               对于如上图所示的例子,选用以下的两组测试用例可以符合条件判定组合覆盖标准:
               . a=T, b=T, c=T。
               . a=F, b=F, c=F。
               但是条件判定组合覆盖也存在一定的缺陷,例如,判定的第一个运算符“&&”错写成运算符“||”或第二个运算符“||”错写成运算符“&&”,如下表所示,这时使用上述的测试用例仍然可以达到100%的条件判定组合覆盖,上述的逻辑错误无法发现。
               
               条件判定组合覆盖
               多条件覆盖(MCC)
               多条件覆盖也称条件组合覆盖,它的含义是:设计足够的测试用例,使得每个判定中条件的各种可能组合都至少出现一次。显然满足多条件覆盖的测试用例是一定满足判定覆盖、条件覆盖和条件判定组合覆盖的。
               对于如下图所示的例子,判定语句中有三个逻辑条件,每个逻辑条件有两种可能取值,因此共有23=8种可能组合,如下表所示的测试用例保证了多条件覆盖。
               
               计算最少测试用例数实例
               
               多条件覆盖
               由上可知,当一个程序中判定语句较多时,其条件取值的组合数目是非常大的。
               修正条件判定覆盖(MCDC)
               修正条件判定覆盖是由欧美的航空/航天制造厂商和使用单位联合制定的“航空运输和装备系统软件认证标准”,目前在国外的国防、航空航天领域应用广泛。这个覆盖度量需要足够的测试用例来确定各个条件能够影响到包含的判定的结果。它要求满足两个条件:首先,每一个程序模块的入口和出口点都要考虑至少要被调用一次,每个程序的判定到所有可能的结果值要至少转换一次;其次,程序的判定被分解为通过逻辑操作符(and、or)连接的bool条件,每个条件对于判定的结果值是独立的。
               对于如下图所示的例子,可以设计如下表中的8个用例,在此基础上,按照MCDC的要求选择需要的用例。
               
               参考例子流程图
               
               修正条件判定覆盖
               从表中我们可以看出,布尔变量a可以通过用例1和5达到MCDC的要求(用例2和6或用例3和7也可以满足相应要求),变量b可以通过用例2和4达到MCDC的要求,变量c可以通过用例3和4达到MCDC的要求,因此使用用例集{1,2,3,4,5}即可满足MCDC的要求。显而易见,这不是惟一的用例组合。
 
       用例设计
        对于这7个场景中的每一个场景都需要确定测试用例,一般采用矩阵或决策表来确定和管理测试用例。如下表所示是一种通用格式,其中行代表各个测试用例,列代表测试用例的信息。本例中的测试用例包含测试用例ID、场景/条件、测试用例中涉及的所有数据元素和预期结果等项目。首先确定执行用例场景所需的数据元素,然后构建矩阵,最后要确定包含执行场景所需的适当条件的测试用例。在下面的矩阵中,V表示这个条件必须是有效的才可执行基本流,I表示这种条件下将激活所需备选流,n/a表示这个条件不适用于测试用例。
        
        测试用例表
        在上面的矩阵中,六个测试用例执行了四个场景。对于基本流,上述测试用例CW1被称为正面测试用例。它一直沿着用例的基本流路径执行,未发生任何偏差。基本流的全面测试必须包括负面测试用例,以确保只有在符合条件的情况下才执行基本流。这些负面测试用例由CW2~CW6表示。虽然CW2~CW6相对于基本流而言都是负面测试用例,但它们相对于备选流2~4而言是正面测试用例。而且对于这些备选流中的每一个而言,至少存在一个负面测试用例,就是CW1-基本流。
        每个场景只有一个正面测试用例和负面测试用例是不充分的,场景4正是这样的一个示例。要全面地测试场景4-PIN有误,至少需要三个正面测试用例,以激活场景4:
        ①输入了错误的PIN,但仍存在输入机会,此备选流重新加入基本流中的步骤3-输入PIN。
        ②输入了错误的PIN,而且不再有输入机会,则此备选流将保留银行卡并终止用例。
        ③最后一次输入时输入了“正确”的PIN。备选流在步骤5-输入金额处重新加入基本流。
        注意,在上面的矩阵中,无需为条件输入任何实际的值。以这种方式创建测试用例矩阵的一个优点在于容易看到测试的是什么条件。由于只需要查看V和I,这种方式还易于判断是否已经确定了充足的测试用例。从上表中可发现存在几个无效的条件I,这表明测试用例还不完全,如场景6-不存在的账户/账户类型有误和场景7-账户余额不足就缺少测试用例。
 
       白盒测试的测试用例设计
        白盒测试是对软件的过程性细节做详细检查。通过对程序内部结构和逻辑的分析来设计测试用例。适合于白盒测试的设计技术主要有:逻辑覆盖法、基本路径测试等。下面将介绍逻辑覆盖法。
        逻辑覆盖(Logic Coverage)是以程序内部的逻辑结构为基础的测试技术。它考虑的是测试数据执行(覆盖)程序的逻辑程度。由于穷举测试是不现实的,因此,只希望覆盖的程度更高些。根据覆盖情况的不同,逻辑覆盖可分为:语句覆盖、判定覆盖、条件覆盖、判定条件覆盖、多重覆盖、路径覆盖。在讨论这几种覆盖时,均以下图所示的程序段为例。这是一个非常简单的程序,共有两个判断、4条不同路径。为了方便起见,分别对第一个判断取假分支,对第一个判断取真分支,对第二个判断取假分支,对第二个判断取真分支并分别命名为b、c、d和e。4条路径表示为abd、acd、abe和ace。其Pascal程序为:
        
        
        被测试程序的流程图
        (1)语句覆盖。
        语句覆盖(Statement Coverage)就是设计若干个检测用例,使得程序中的每条语句至少被执行一次。在所举的示例中,只要选择能通过路径ace的测试用例即可。如:
        
        语句覆盖对程序的逻辑覆盖程度很低,如果把第一个判断语句中的AND错写成OR,或把第二个判断语句中的OR错写成AND,用上面的测试用例是不能发现问题的。这说明语句覆盖有可能发现不了判断条件中算法出现的错误。
        (2)判定覆盖。
        判定覆盖(Decision Coverage)也被称为分支覆盖,就是设计若干个检测用例,使得程序中的每个判断的取真分支和取假分支至少被执行一次。对上述被测程序来说,需要设计测试用例覆盖路径acd和abe(或abd和ace)。可以选择如下的输入数据:
        
        还可以选择另外两组输入数据:
        
        判断覆盖比语句覆盖的程度稍高,因为如果通过了每个分支的测试,则各语句也都被执行了。但仍有不足,如上述的测试用例不能发现把第二个判断语句中的X>1错写成X<1的错误。所以,判断覆盖还不能保证一定能查出判断条件中的错误。因此,需要更强的逻辑覆盖来检测内部条件的错误。
        (3)条件覆盖。
        条件覆盖(Condition Coverage)就是设计若干个测试用例,使得被测程序中每个判断的每个条件的所有可能情况都至少被执行一次。
        上述被测程序,共有4个条件:
        
        为此,需要设计测试用例,使得a点出现测试结果:
        
        并使b点出现测试结果:
        
        可以设计两组测试输入数据:
        
        条件覆盖通常比判断覆盖强,因为条件覆盖可以使判断语句中的每个条件都能取两个不同的结果。但有可能出现虽然每个条件都取了不同的结果,但判断表达式却始终是一个值的情况,请看下面两组输入数据:
        
        它们满足条件覆盖,但不满足语句覆盖和判断覆盖的标准(未经历路径c,那么就发现不了X=X/A错写成X=X/B的错误)。因此,需要对条件及判断产生的分支兼顾,这就是下面要介绍的判断/条件覆盖。
        (4)判断/条件覆盖。
        判断/条件覆盖(Decision/Condition Coverage)是既要满足判断覆盖的要求,又要满足条件覆盖的要求。也就是设计若干个测试用例,使得程序中的每个判断的取真分支和取假分支至少执行一次,而且每个条件的所有可能情况都至少被执行一次。对于上图而言,下面两组输入数据可以满足判断/条件覆盖的要求:
        
        但这两组数据也是条件覆盖中所举的示例。因此,有时判断/条件覆盖并不比条件覆盖更强,逻辑表达式的错误也不一定能被检查出来。
        (5)多重覆盖。
        多重覆盖(Multi-job Coverage)就是设计多个测试用例,使得各判断表达式中条件的各种组合至少被执行一次。就上图所示的例子而言,要符合多重覆盖的标准,所设计的测试用例必须满足下面的8种条件组合:
        
        要测试到这8种情况,可以选择下列4组输入数据:
        
        很显然,多重覆盖包含了条件覆盖、判断覆盖和判断/条件覆盖,是前面几种覆盖标准中最强的。但就上面的4组输入数据,也没有将程序中的每条路径都覆盖了,如:没有通过acd这条路径,所以测试仍不完全。
        (6)路径覆盖。
        路径覆盖就是设计足够多的测试示例,使被测程序中的所有可能路径至少被执行一次。对上面的例子束说,可以选择这样的4组测试数据来覆盖程序中的所有路径:
        
        路径覆盖保证了程序中的所有路径都至少被执行一次,是一种比较全的逻辑覆盖标准。但它没有检查判断表达式中条件的各种组合情况,通常把路径覆盖和多重覆盖结合起来就可以得到查错能力很强的测试用例。如上面的例子,把多重覆盖的4组输入数据和路径覆盖中的第3组数据组合成起来,形成5组输入数据,就可以得到既满足路径覆盖的标准,又满足多重覆盖的标准。
        (7)循环覆盖。
        上面介绍的只是语句、分支、条件以及它们的组合情况,而循环也是大多数算法的基础:对循环的测试主要检查循环构造的有效性。循环分为简单循环(Simple Loops)、串联循环(Concatenated Loops)、嵌套循环(Nested Loops)和非结构循环(Unstructured Loops)4种类型,如下图所示。
        
        循环的4种类型
        对于循环次数为n的简单循环。可以采用下列措施进行测试。
        .跳过整个循环。
        .循环次数为1,2,n-1,n,n+1。
        .任取循环次数为m,其中m
        对于嵌套循环,如果采用简单循环的测试方法,则测试次数将会成几何级数增长。可以采用以下方法进行测试。
        .从最内层循环开始测试,对所有外层循环都取最小值,内层循环按简单循环的测试方法进行。
        .由里向外,一层层进行测试,凡是外层的循环都取最小值,该层循环嵌套的那些循环取一些典型的值。
        .直至所有循环测试完毕。
        对于串联循环的测试可分成两种情况:如果两个循环是独立的,则采用简单循环的测试方法;反之,如果两个循环不是独立的,则需要用嵌套循环的测试方法来测试,对于非结构循环,一般先把程序结构化之后再进行测试。
 
       测试用例设计
               白盒测试的测试用例设计
               白盒测试是对软件的过程性细节做详细检查。通过对程序内部结构和逻辑的分析来设计测试用例。适合于白盒测试的设计技术主要有:逻辑覆盖法、基本路径测试等。下面将介绍逻辑覆盖法。
               逻辑覆盖(Logic Coverage)是以程序内部的逻辑结构为基础的测试技术。它考虑的是测试数据执行(覆盖)程序的逻辑程度。由于穷举测试是不现实的,因此,只希望覆盖的程度更高些。根据覆盖情况的不同,逻辑覆盖可分为:语句覆盖、判定覆盖、条件覆盖、判定条件覆盖、多重覆盖、路径覆盖。在讨论这几种覆盖时,均以下图所示的程序段为例。这是一个非常简单的程序,共有两个判断、4条不同路径。为了方便起见,分别对第一个判断取假分支,对第一个判断取真分支,对第二个判断取假分支,对第二个判断取真分支并分别命名为b、c、d和e。4条路径表示为abd、acd、abe和ace。其Pascal程序为:
               
               
               被测试程序的流程图
               (1)语句覆盖。
               语句覆盖(Statement Coverage)就是设计若干个检测用例,使得程序中的每条语句至少被执行一次。在所举的示例中,只要选择能通过路径ace的测试用例即可。如:
               
               语句覆盖对程序的逻辑覆盖程度很低,如果把第一个判断语句中的AND错写成OR,或把第二个判断语句中的OR错写成AND,用上面的测试用例是不能发现问题的。这说明语句覆盖有可能发现不了判断条件中算法出现的错误。
               (2)判定覆盖。
               判定覆盖(Decision Coverage)也被称为分支覆盖,就是设计若干个检测用例,使得程序中的每个判断的取真分支和取假分支至少被执行一次。对上述被测程序来说,需要设计测试用例覆盖路径acd和abe(或abd和ace)。可以选择如下的输入数据:
               
               还可以选择另外两组输入数据:
               
               判断覆盖比语句覆盖的程度稍高,因为如果通过了每个分支的测试,则各语句也都被执行了。但仍有不足,如上述的测试用例不能发现把第二个判断语句中的X>1错写成X<1的错误。所以,判断覆盖还不能保证一定能查出判断条件中的错误。因此,需要更强的逻辑覆盖来检测内部条件的错误。
               (3)条件覆盖。
               条件覆盖(Condition Coverage)就是设计若干个测试用例,使得被测程序中每个判断的每个条件的所有可能情况都至少被执行一次。
               上述被测程序,共有4个条件:
               
               为此,需要设计测试用例,使得a点出现测试结果:
               
               并使b点出现测试结果:
               
               可以设计两组测试输入数据:
               
               条件覆盖通常比判断覆盖强,因为条件覆盖可以使判断语句中的每个条件都能取两个不同的结果。但有可能出现虽然每个条件都取了不同的结果,但判断表达式却始终是一个值的情况,请看下面两组输入数据:
               
               它们满足条件覆盖,但不满足语句覆盖和判断覆盖的标准(未经历路径c,那么就发现不了X=X/A错写成X=X/B的错误)。因此,需要对条件及判断产生的分支兼顾,这就是下面要介绍的判断/条件覆盖。
               (4)判断/条件覆盖。
               判断/条件覆盖(Decision/Condition Coverage)是既要满足判断覆盖的要求,又要满足条件覆盖的要求。也就是设计若干个测试用例,使得程序中的每个判断的取真分支和取假分支至少执行一次,而且每个条件的所有可能情况都至少被执行一次。对于上图而言,下面两组输入数据可以满足判断/条件覆盖的要求:
               
               但这两组数据也是条件覆盖中所举的示例。因此,有时判断/条件覆盖并不比条件覆盖更强,逻辑表达式的错误也不一定能被检查出来。
               (5)多重覆盖。
               多重覆盖(Multi-job Coverage)就是设计多个测试用例,使得各判断表达式中条件的各种组合至少被执行一次。就上图所示的例子而言,要符合多重覆盖的标准,所设计的测试用例必须满足下面的8种条件组合:
               
               要测试到这8种情况,可以选择下列4组输入数据:
               
               很显然,多重覆盖包含了条件覆盖、判断覆盖和判断/条件覆盖,是前面几种覆盖标准中最强的。但就上面的4组输入数据,也没有将程序中的每条路径都覆盖了,如:没有通过acd这条路径,所以测试仍不完全。
               (6)路径覆盖。
               路径覆盖就是设计足够多的测试示例,使被测程序中的所有可能路径至少被执行一次。对上面的例子束说,可以选择这样的4组测试数据来覆盖程序中的所有路径:
               
               路径覆盖保证了程序中的所有路径都至少被执行一次,是一种比较全的逻辑覆盖标准。但它没有检查判断表达式中条件的各种组合情况,通常把路径覆盖和多重覆盖结合起来就可以得到查错能力很强的测试用例。如上面的例子,把多重覆盖的4组输入数据和路径覆盖中的第3组数据组合成起来,形成5组输入数据,就可以得到既满足路径覆盖的标准,又满足多重覆盖的标准。
               (7)循环覆盖。
               上面介绍的只是语句、分支、条件以及它们的组合情况,而循环也是大多数算法的基础:对循环的测试主要检查循环构造的有效性。循环分为简单循环(Simple Loops)、串联循环(Concatenated Loops)、嵌套循环(Nested Loops)和非结构循环(Unstructured Loops)4种类型,如下图所示。
               
               循环的4种类型
               对于循环次数为n的简单循环。可以采用下列措施进行测试。
               .跳过整个循环。
               .循环次数为1,2,n-1,n,n+1。
               .任取循环次数为m,其中m
               对于嵌套循环,如果采用简单循环的测试方法,则测试次数将会成几何级数增长。可以采用以下方法进行测试。
               .从最内层循环开始测试,对所有外层循环都取最小值,内层循环按简单循环的测试方法进行。
               .由里向外,一层层进行测试,凡是外层的循环都取最小值,该层循环嵌套的那些循环取一些典型的值。
               .直至所有循环测试完毕。
               对于串联循环的测试可分成两种情况:如果两个循环是独立的,则采用简单循环的测试方法;反之,如果两个循环不是独立的,则需要用嵌套循环的测试方法来测试,对于非结构循环,一般先把程序结构化之后再进行测试。
               黑盒测试的测试用例设计
               黑盒测试是在测试时把软件看成一个黑盒子,完全不考虑程序的内部结构及其逻辑,重点考察程序功能是否与需求说明书的要求一致。适合于黑盒测试的设计技术主要有:等价类划分、边界值分析、错误推测法、因果图、功能图等。下面重点介绍等价类划分、边界值分析这两种测试技术。
               (1)等价类划分。
               等价类划分是比较典型的黑盒测试技术。如前所述,输入量的穷举测试是不现实的,那么如何才能既可大大减少测试的次数、又不丢失发现错误的机会是问题的关键所在。等价类划分技术的主要思想就是程序的输入数据都可以按照程序说明划分为若下个等价类,每一个等价类对于输入条件可划分为有效的输入和无效的输入,然后再对每一个有效的等价类和无效的等价类设计测试用例。如果用某个等价类的一组测试数据进行测试时没有发现错误,则说明在同一等价类中的其他输入数据也一样查不出问题;反之,如用某个等价类的测试数据进行测试,并检查出错误,则说明用该等价类的其他输入数据进行测试也一样会检测出错误。所以在测试时,只需从每个等价类中取一组输入数据进行测试即可。
               使用等价类划分技术设计测试方案时,首先需要根据程序的功能说明划分出输入数据的有效等价类和无效等价类,然后为每个等价类设计测试用倒。在确定输入数据的等价类时常常还需要分析输出数据的等价类,以便根据输出数据的等价类来推导出对应的测试用例。
               在划分等价类时,可以按以下原则进行。
               .如果规定了输入数据的范围,则可划分为一个有效等价类和两个无效等价类。如学生年龄输入的范围为0~100,则有效等价类为“0≤年龄≤100”,两个无效等价类为“年龄>100”或“年龄<0”。
               .如果规定了输入数据的个数,则可划分为一个有效等价类和两个无效等价类。如一个老师在指导毕业设计时必须指导1~5个学生,则有效等价类为“学生人数是1~5个”,两个无效等价类为“一个都不指导”或“指导人数超过5个”。
               .如果规定了输入数据为一组可能的值,而且程序对每个输入值分别进行处理,这时需要为每个输入数据确定一个有效等价类,把除此之外的所有值确定为一个无效等价类。如在教师涨工资的方案中根据职称(教授、副教授、讲师和助教)的不同其增长幅度也不相同,这时需要对每个职称确定一个有效的等价类(共4个),还有一个无效的等价类,它包含不满足以上身份的所有输入数据。但是,如果在程序对这些可能值的处理都一样时,只需要确定一个有效等价类(所有合理值)和一个无效等价类(除合理值之外的其他任何值)。
               .如果规定了输入数据必须遵守的规则,则可以划分出一个有效等价类(遵守规则的输入数据)和若干个无效等价类(从不同角度设计得到违反规则的情况)。
               .如果在划分的某等价类中各值在程序中的处理方式不同,则需要将该等价类进一步划分成更小的等价类。
               以上列出的原则只是实际情况中很小的一部分。为了正确划分等价类,需要正确分析被测程序的功能。划分等价类的方法是根据每个输入条件(通常是规范说明中的一句话或一个短语)列出两个或更多的等价类,将其填入下表中,建立等价类表。
               
               等价类表
               根据等价类表设计测试用例,完成下面两个步骤。
               .设计新的测试用例,使其尽可能多地覆盖未被覆盖的有效等价类,重复这一步骤直至所有有效等价类都被覆盖。
               .设计新的测试用例,使其覆盖一个而且仅此一个未被覆盖的无效等价类,重复这一步骤直至所有无效等价类都被覆盖。
               之所以这么做,是因为程序在遇到错误之后就不会再检查是否还有其他错误。所以一个测试用例只能覆盖一个无效等价类。
               例如,判断是否为三角形的条件是其中任意两个数之和应大于第三个数。假入输入的三个数表示三角形的三个边,可以建立如下表所示的等价类表。
               
               三角形判断的等价类表
               根据等价类表可设计如下测试用例:
               
               (2)边界值分析。
               边界值分析也是黑盒测试技术,是等价类划分的一种补充。通常,程序在处理边界时容易发生错误。而等价类划分技术是在等价类中随便选择一组数据作为代表,并没有考虑边界情况。边界值分析是指将每个等价类的各边界作为测试目标,使得测试数据等于、刚刚小于、或刚大于等价类的边界值。
               边界值分析技术在设计测试用例的原则与等价类划分技术的许多方面类似。需要注意的是,边界值分析技术不仅应注意输入条件的边值,还应根据输出条件的边值设计测试用例(下面的④、⑤原则就是针对输出条件的边值问题)。选择测试用例有以下原则:
               ①如果规定了输入数据的范围,则应取等于该范围的边界值,以及刚刚超过这个范围的边界值的测试数据。如某数输入的范围是从0~1.0,则可选“-0.01”、“0”、“1.0”和“1.01”作为测试数据。
               ②如果规定了输入数据的个数,则应取最大个数、最小个数、比最大个数多1和比最小个数少1的数作为测试数据。如一个老师在指导毕业设计时必须指导1~5个学生,则可选指导人数分别为0个、1个、5个和6个作为测试数据。
               ③如果程序中使用了内部数据结构,则需要选择该数据结构的边界值作为测试用例。如在程序中使用了一个数组,其下标值的范围为0~20,这就需要选择达到该数组的下标边界值(即0与20)作为测试数据。
               ④根据规格说明的每个输出条件可以使用第①条原则。如某个被测程序的输出值在0~1之间,则需要设计测试用例使得其输出值分别为0和1。
               ⑤根据规格说明的每个输出条件也可以使用第②条原则。如某个被测程序在显示时要求显示的记录数最多为5条,则需要设计测试用例使得其输出的记录数分别为0条、1条和5条。
               例如,前面的三角形判断示例中,如果把a+b>c错误写成a+b≥c,等价类划分方法通常无法发现这个错误。使用边界值分析技术,则会选择这样的测试用例:
               
               这组数据就能发现上述错误。
               从这里可以看出,边界值分折与等价类划分技术最大的区别是边界值分析技术在设计测试用例时,将重点检测等价类边界和边界附近的情况,而等价类划分技术只是在每个等价类中随便选择一组测试数据。
               在设计测试方案中,通常会把逻辑覆盖、等价类划分和边界值分析等方法结合起来,这样既可以检测设计的内部要求,又可以检测设计的接口要求。
               在对非常庞大、复杂的信息系统进行测试时,如果严格按照上面所介绍的测试技术进行,所花费的人力、时间无疑是非常大的。考虑到测试中存在着群集现象以及软件的可重用性,在实际的测试过程中,可以采用抽样测试或重点测试。也就是有针对性地选择具有代表性的测试用例进行测试,或把测试的重点放在容易出错的地方及重要模块上。这样可以以较少资源发现错误,也就提高了测试效率。
   题号导航      2009年上半年 软件评测师 上午试卷 综合知识   本试卷我的完整做题情况  
1 /
2 /
3 /
4 /
5 /
6 /
7 /
8 /
9 /
10 /
11 /
12 /
13 /
14 /
15 /
 
16 /
17 /
18 /
19 /
20 /
21 /
22 /
23 /
24 /
25 /
26 /
27 /
28 /
29 /
30 /
 
31 /
32 /
33 /
34 /
35 /
36 /
37 /
38 /
39 /
40 /
41 /
42 /
43 /
44 /
45 /
 
46 /
47 /
48 /
49 /
50 /
51 /
52 /
53 /
54 /
55 /
56 /
57 /
58 /
59 /
60 /
 
61 /
62 /
63 /
64 /
65 /
66 /
67 /
68 /
69 /
70 /
71 /
72 /
73 /
74 /
75 /
 
第55题    在手机中做本题