友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
富士康小说网 返回本书目录 加入书签 我的书架 我的书签 TXT全本下载 『收藏到我的浏览器』

软件测试的艺术(中文清晰版)(PDF格式)-第3部分

快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!





这就说明为什么大多数人都觉得它困难。这种定义可能是违反我们愿望的;所幸 



的是,我们大多数人总是对生活充满建设性而不是破坏性的愿景。大多数人都本 



能地倾向于创造事物,而不是将事物破坏。这个定义还暗示了对于一个特定的程序, 



应该如何设计测试用例(测试数据)、哪些人应该而哪些人又不应该执行测试。 



  为增进对软件测试正确定义的理解,另一条途径是分析一下对“成功的”和 



“不成功的”这两个词的使用。当项目经理在归纳测试用例的结果时,尤其会用到 



这两个词。大多数的项目经理将没发现错误的测试用例称为一次“成功的测试”, 



而将发现了某个新错误的测试称为“不成功的测试”。 



  这又是一次本末倒置。“不成功的”表示事情不遂人意或令人失望。我们认为, 



如果在测试某段程序时发现了错误,而且这些错误是可以修复的,就将这次合理 



设计并得到有效执行的测试称做是“成功的”。如果本次测试可以最终确定再无其 



他可查出的错误,同样也被称做是“成功的”。所谓“不成功的”测试,仅指未能 



适当地对程序进行检查,在大多数情况下,未能找出错误的测试被认为是“不成 



功的”,这是因为认为软件中不包含错误的观点基本上是不切实际的。 



  能发现新错误的测试用例不太可能被认为是“不成功的”,也就是说,能发现 



错误就证明它是值得设计的。“不成功的”测试用例,会看到程序输出正确的结果 


…………………………………………………………Page 18……………………………………………………………

6  软件测试的艺术 



而没发现任何错误。 



  我们可以类比一下病人看医生的情况,病人因为身体不舒服而去看医生。如 



果医生对病人进行了一些检查和化验,却没有诊断出任何病因,我们就不会认为 



这些检查和化验是“成功的”,因为病人支付了昂贵的检查和化验费用,而病状却 



依然如故。病人会因此而质疑医生的诊断能力。但是,如果医生诊断出病人是胃 



溃疡,那么这次检测就是“成功的”,医生可以开始进行相应的治疗。因此,医疗 



行业会使用“成功的”或“不成功的”来表达诊断结果。我们当然可以类推到软 



件测试中来,当我们开始测试某个程序时,它就好似我们的病人。 



  “软件测试就是证明软件不存在错误的过程”,这个定义会带来第二个问题。对 



于几乎所有的程序而言,甚至是非常小的程序,这个目标实际上也是无法达到的。 



  另外,心理学研究表明,当人们开始一项工作时,如果已经知道它是不可行 



的或无法实现时,人的表现就会相当糟糕。举例来说,如果要求人们在15分钟之 



内完成星期日《纽约时报》里的纵横填字游戏,那么我们会观察到10分钟之后的 



进展非常小,因为大多数人都会却步于这个现实,即这个任务似乎是不可能完成 



的。但是如果要求在四个小时之内完成填字游戏,我们很可能有理由期望在最初 



10分钟之内的进展会比前一种情况下的大。将软件测试定义为发现程序错误的过 



程,使得测试是个可以完成的任务,从而克服了这个心理障碍。 



  诸如“软件测试就是证明‘软件做了其应该做的’的过程”此类的定义所带 



来的第三个问题是,程序即使能够完成预定的功能,也仍然可能隐藏错误。也就 



是说,当程序没有实现预期功能时,错误是清晰地显现出来的;如果程序做了其 



不应该做的,这同样是一个错误。考虑一下第1章中的三角形测试程序。即使我们 



证明了程序能够正确识别出不规则三角形、等腰三角形和等边三角形,但是在完 



成了不应执行的任务后(例如将1,2 ,3说成是一个不规则三角形或将0 ,0 ,0说 



成是一个等边三角形),程序仍然是错的。如果我们将软件测试视作发现错误的过 



程,而不是将其视为证明“软件做了其应该做的”的过程,我们发现后一类错误 



的可能性会大很多。 



  总结一下,软件测试更适宜被视为试图发现程序中错误(假设其存在)的破 



坏性的过程。一个成功的测试用例,通过诱发程序发生错误,可以在这个方向上 



促进软件质量的改进。当然,最终我们还是要通过软件测试来建立某种程度的信 



心:软件做了其应该做的,未做其不应该做的。但是通过对错误的不断研究是实 


…………………………………………………………Page 19……………………………………………………………

                       第2章 软件测试的心理学和经济学   7 



现这个目的的最佳途径。 



  有人可能会声称“本人的程序完美无缺”(不存在错误),针对这种情况建立 



起信心的最好办法就是尽量反驳他,即努力发现不完美之处,而不只是确认程序 



在某些输入情况下能够正确地工作。 



2。2   软件测试的经济学 



  给出了软件测试的适当定义之后,下一步就是确定软件测试是否能够发现 



“所有”的错误。我们将证明答案是否定的,即使是规模很小的程序。一般说来, 



要发现程序中的所有错误也是不切实际的,常常也是不可能的。这个基本的问题 



反过来暗示出软件测试的经济学问题、测试人员对被测软件的期望,以及测试用 



例的设计方式。 



  为了应对测试经济学的挑战,应该在开始测试之前建立某些策略。黑盒测试 



和白盒测试是两种最普遍的策略,我们将在下面两节中讨论。 



2。2。1   黑盒测试 



  黑盒测试是一种重要的测试策略,又称为数据驱动的测试或输入/输出驱动的 



测试。使用这种测试方法时,将程序视为一个黑盒子。测试目标与程序的内部机制 



和结构完全无关,而是将重点集中放在发现程序不按其规范正确运行的环境条件。 



  在这种方法中,测试数据完全来源于软件规范(换句话说,不需要去了解程 



序的内部结构)。 



  如果想用这种方法来发现程序的所有错误,判定的标准就是“穷举输入测试”, 



将所有可能的输入条件都作为测试用例。为什么这样做?比如说在三角形测试的 



程序中,试过了三个等边三角形的测试用例,这不能确保正确地判断出所有的等 



边三角形。程序中可能包含对边长为3842 ,3842 ,3842 的特殊检查,并指出此三 



角形为不规则三角形。由于程序是个黑盒子,因此能够确定此条语句存在的惟一 



方法,就是试验所有的输入情况。 



  要穷举测试这个三角形程序,可能需要为所有有效的三角形创建测试用例, 



只要三角形边长在开发语言允许的最大整数值范围内。这些测试用例本身就是天 



文数字,但这还绝不是所谓穷尽的;当程序指出-3 ,4 ,5是一个不规则三角形或 



2 ,A ,2是一个等腰三角形时,问题就暴露出来了。为了确保能够发现所有这样的 


…………………………………………………………Page 20……………………………………………………………

8  软件测试的艺术 



错误,不仅得用所有有效的输入,而且还得用所有可能的输入进行测试。因此, 



为了穷举测试三角形程序,实际上需要创建无限的测试用例,这当然是不可能的。 



  如果测试这个三角形程序都这么难的话,那么要穷举测试一个稍大些的程序 



的难度就更大了。设想一下,如果要对一个C++编译器进行黑盒穷举测试,不仅 



要创建代表所有有效C++程序的测试用例(实际上,这又是一个无穷数),还需要 



创建代表所有无效C++程序的测试用例(无穷数),以确保编译器能够检测出它们 



是无效的。也就是说,编译器必须进行测试,确保其不会执行不应执行的操作— 



如顺利地编译成功一个语法上不正确的程序。 



  如果程序使用到数据存储,如操作系统或数据库应用程序,这个问题会变得 



尤为严重。举例来说,在航班预定系统这样的数据库应用程序中,诸如数据库查 



询、航班预约这样的事务处理需要随上一次事务的执行情况而定。因此,不仅要 



测试所有有效的和无效的事务处理,还要测试所有可能的事务处理顺序。 



  上述讨论说明,穷举输入测试是无法实现的。这有两方面的含义,一是我们 



无法测试一个程序以确保它是无错的,二是软件测试中需要考虑的一个基本问题 



是软件测试的经济学。也就是说,由于穷举测试是不可能的,测试投入的目标在 



于通过有限的测试用例,最大限度地提高发现的问题的数量,以取得最好的测试 



效果。除了其他因素之外,要实现这个目标,还需要能够窥见软件的内部,对程 



序作些合理但非无懈可击的假设(例如,如果三角形程序将2 ,2 ,2视为等边三角 



形,那就有理由认为程序对3 ,3 ,3也作同样判断)。这种思路将形成本书第4 章中 



测试用例设计策略的部分方法。 



2。2。2    白盒测试 



  另一种测试策略称为白盒测试或称逻辑驱动的测试,允许我们检查程序的内部 



结构。这种测试策略对程序的逻辑结构进行检查,从中获取测试数据(遗憾的是, 



常常忽略了程序的规范)。 



  在这里我们的目标是针对这种测试策略,建立起与黑盒测试中穷举输入测试 



相似的测试方法。也许有一个解决的办法,即将程序中的每条语句至少执行一次。 



但是我们不难证明,这还是远远不够的。这种方法通常称为穷举路径测试,在本 



书第4 章中将进一步进行深入探讨,在这里就不多加叙述。所谓穷举路径测试,即 



如果使用测试用例执行了程序中所有可能的控制流路径,那么程序有可能得到了 


…………………………………………………………Page 21……………………………………………………………

                          第2章 软件测试的心理学和经济学       9 



完全测试。 



   然而,这个论断存在两个问题。首先,程序中不同逻辑路径的数量可能达到天 



文数字。图2…1所示的小程序显示 



了这一点。该图是一个控制流图,                      a 



每一个结点或圆圈都代表一个按 



顺序执行的语句段,通常以一个 



分支语句结束。每一条边或弧线 



表示语句段之间的控制(分支) 



的转换。图2…1描述的是一个有着 



10~20 行语句的程序,包含一个 



迭代20 次的DO 循环。在DO 循环 



体中,包含一系列嵌套的IF语句。 



要确定不同逻辑路径的数量,也 



相当于要确定从点a ~点b 之间所 



有不同路径的数量(假定程序中 



所有的判断语句都是相互独立 

                                    b 

的)。这个数量大约是1 0 1 4 ,即 



          20 19  1 

100万亿,是从5  +5 …+5  计算 

                           图2…1   一个小型程序的控制流图 

而来,5是循环体内的路径数量。 



由于大多数的人难以对这个数字有一个直观的概念,不妨设想一下:如果在每五 



分钟内可以编写、执行和确认一个测试用例,那么需要大约10亿年才能测试完所 



有的路径。假如可以快上300倍,每一秒就完成一次测试,也得用漫长的320万年 



才能完成这项工作。 



   当然,在实际程序中,判断并非都是彼此独立的,这意味着可能实际执行的 



路径数量要稍微少一些。但是,从另一方面来讲,实际应用的程序要比图2…1所描 



述的简单程序复杂得多。因此,穷举路径测试就如同穷举输入测试,非但不可能, 



也是不切实际的。 



   “穷举路径测试即完全的测试”论断存在的第二个问题是,虽然我们可以测试 



到程序中的所有路径,但是程序可能仍然存在着错误。这有三个原因。 



   第一,即使是穷举路径测试也决不能保证程序符合其设计规范。举例来说, 


…………………………………………………………Page 22……………………………………………………………

10  软件测试的艺术 



如果要编写一个升序排序程序,但却错误地编成了一个降序排序程序,那么穷举 



路径测试就没多大价值了;程序仍然存在着一个缺陷:它是个错误的程序,因为 



不符合设计的规范。 



  第二,程序可能会因为缺少某些路径而存在问题。穷举路径测试当然不能发 



现缺少了哪些必需路径。 



  第三,穷举路径测试可能不会暴露数据敏感错误。这样的例子有很多,举一 



个简单的例子就能说明问题。假设在某个程序中要比较两个数值是否收敛,也就 



是检查两个数值之间的差异是否小于某个既定的值。我们可能会这样编一条Java 



语言的IF语句: 



当然,这条语句明显错了,因为程序原意是将c与a…b 的绝对值进行比较。然而,要 



找出这样的错误,取决于a和b 所取的值,而仅仅执行程序中的每条路径并不一定 



能找出错误来。 



  总之,尽管穷举输入测试要强于穷举路径测试,但两者都不是有效的方法, 



因为这两种方法都不可行。那么,也许存在别的方法,将黑盒测试和白盒测试的 



要素结合起来,形成一个合理但并不十分完美的测试策略。本书的第4 章将深入讨 



论这个话题。 



2。3   软件测试的原则 



  让我们继续本章的话题基础,即软件测试中大多数重要的问题都是心理学问 



题。我们可以归纳出一系列重要的测试指导原则。这些原则看上去大多都是显而 



易见的,但常常总是被我们忽视掉。表2…1总结了这些重要原则,每条原则都将在 



下面的章节中详细介绍。 



                  表2…1   软件测试的重要原则 



 编  号                    原  则 



   1    测试用例中一个必需部分是对预期输出或结果进行定义 



   2    程序员应当避免测试自己编写的程序 



   3    编写软件的组织不应当测试自己编写的软件 



   4    应当彻底检查每个测试的执行结果 


…………………………………………………………Page 23……………………………………………………………

                         第2章 软件测试的心理学和经济学    11 



                                          (续) 



 编  号                     原  则 



   5    测试用例的编写不仅应当根据有效和预料到的输入情况,而且也应当根据无效和未预 



       料到的输入情况 



   6    检查程序是否“未做其应该做的”仅是测试的一半,测试的另一半是检查程序是否 



       “做了其不应该做的” 



   7    应避免测试用例用后即弃,除非软件本身就是一个一次性的软件 



   8    计划测试工作时不应默许假定不会发现错误 



   9    程序某部分存在更多错误的可能性,与该部分已发现错误的数量成正比 



   10   软件测试是一项极富创造性、极具智力挑战性的工作 



   原则1:测试用例中一个必需部分是对预期输出或结果的定义。 



   这条显而易见的原则在软件测试中是最常犯的错误之一。同样,这个问题也是 



基于人们的心理的。如果某个测试用例的预期结果事先没有得到定义,由于“所见 



即所想”现象的存在,某个似是而非、实际上是错误的结果可能会被解释成正确的 



结论。换句话说,尽管“软件测试是破坏性”的定义是合理的,但人们在潜意识中 



仍然渴望看到正确的结果。克服这种倾向的一种方法,就是通过事先精确定义程序 



的预期输出,鼓励人们对所有的输出进行仔细检查。因此,一个测试用例必须包括 



两个部分: 



   1。 对程序的输入数据的描述。 



   2。 对程序在上述输入数据下的正确输出结果的精确描述。 



   所谓“问题”,可以归纳为一个或一组我们不能给出可信服的解释、看上去不 



太正常或不符合我们期望或预想的事实。应当明确的是,在确定事物存在“问题” 



之前,人们必须已经形成了特定的认识。没有期望,也就没有所谓的意外。 



   原则2 :程序员应当避免测试自己编写的程序。 



   任何作者都知道或应该知道,亲自编辑或校对自己的作品确实是个不好的做 



法。作者清楚某段文字要说明的是什么,实际表达出来的意思却南辕北辙,而自 



己可能却意识不到。况且实际上也不会想在自己的作品中找出什么错误来。对程 



序员而言,也存在相同的问题。 



   如果我们对软件项目关注的重点发生变化,就会产生另外一个问题。当程序 



员“建设性”地设计和编写完程序之后,很难让他突然改变视角以一种“破坏性” 



的眼光来审查程序。 


…………………………………………………………Page 24……………………………………………………………

12  软件测试的艺术 



  正如许多房屋业主都知道的那样,撕下屋里的墙纸(这是个破坏性的过程) 



并不容易,如果这些墙纸又恰恰是业主第一个亲手贴的,尤其令其沮丧不已。同 



样,大多数程序员都不能有效地测试自己编写的程序,因为他们无法改变思维方 



式来尽力暴露自己程序中的错误。另外,程序员可能会下意识地避免找出错误来, 



担心受到同事、上司、客户或正在开发的程序或系统的主管的惩罚。 



  仅次于上面的心理学问题,还有一个重要的问题:由于程序员错误地理解了 



疑难定义或规范,导致程序中存在错误。如果情况是这样,程序员可能会带着同 



样的误解来测试自己的程序。 



  这并不意味着程序员测试自己的程序是不可能的。当然,我们的言下之意是, 



让其他人来测试程序会更加有效,也会更容易测试成功。 



  请注意,我们的论据并不适合于“调试”(纠正已知的错误)。“调试”由程序 



的编写人员来完成会有效得多。 



  原则3 :编写软件的组织不应当测试自己编写的软件。 



  这里的论据与前面的论据相似。从很多方面来讲,一个软件项目或编程组织 



是一个有机的机构,具有与个体程序员相似的心理问题。而且在大多数情况下, 



主要是根据其在给定时间、特定成本范围内开发软件的能力来衡量编程组织或项 



目经理。其中的一个原因是,度量时间和成本目标比较容易,而定量地衡量软件 



的可靠性则极其困难。即便是合理规划和实施的测试过程,也可能被认为降低了 



完成进度和成本目标的可能性,因此,编程组织难以客观地测试自己的软件。 



  同样,我们并不是说编程组织发现程序中的问题是不可能的,事实上很多组 



织已经在某种程度上成功地做到了这一点。当然,我们的言下之意是,更经济的 



方法是由客观、独立的第三方来进行测试。 



  原则4 :应当彻底检查每个测试的执行结果。 



  这个原则可能是最显而易见的原则,但也同样常常被忽视。我们见过大量的 



例子,即便错误的症状在输出清单中可以清楚地看到,但还是没有找出那些错误 



来。换言之,在后续测试中发现的错误,往往是前面的测试遗漏掉的。 



  原则5 :测试用例的编写不仅应当根据有效和预期的输入情况,而且也应当根 



据无效和未预料到的输入情况。 



  在测试软件时,有一个自然的倾向,即将重点
返回目录 上一页 下一页 回到顶部 9 9
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!