友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
软件测试的艺术(中文清晰版)(PDF格式)-第4部分
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!
据无效和未预料到的输入情况。
在测试软件时,有一个自然的倾向,即将重点集中在有效和预期的输入情况
上,而忽略了无效和未预料到的情况。比如,在本书第1章三角形程序的测试中,
…………………………………………………………Page 25……………………………………………………………
第2章 软件测试的心理学和经济学 13
总是出现这个倾向。
例如,很少有人会向程序输入1,2 ,5 以证明程序不会错误地将其解释为一个
不规则三角形,而不是一个无效三角形。此外,在软件产品中突然暴露出来的许多
问题是当程序以某些新的或未预料到的方式运行时发现的。因此,针对未预料到的
和无效输入情况的测试用例,似乎比针对有效输入情况的那些用例更能发现问题。
原则6 :检查程序是否“未做其应该做的”仅是测试的一半,测试的另一半是
检查程序是否“做了其不应该做的”。
这条原则是上条原则的必然结果。必须检查程序是否有我们不希望的负作用。
比如,某个工资管理程序即便可以生成正确的工资单,但是如果也为非雇员生成
工资单或者它覆盖掉了人员文件的第一条记录,这样的程序仍然是不正确的程序。
原则7 :应避免测试用例用后即弃,除非软件本身就是一个一次性的软件。
这个问题在采用交互式系统来测试软件时最常见。人们通常会坐在终端前,匆
忙地编写测试用例,然后将这些用例交由程序执行。这样做的问题在于,饱含我们
宝贵投入的测试用例,在测试结束后就消失了。一旦软件需要重新测试(例如,当
改正了某个错误或作了某种改进后),又必须重新设计这些测试用例。情况往往是
这样的,由于重新设计测试用例需要投入大量的工作,人们总是避免这样做。因此,
对该程序的重新测试极少会同上次一样严格。这就意味着,如果对程序的更改导致
了程序某个先前可以执行的部分发生了故障,这个故障往往是不会被发现的。保留
测试用例,当程序其他部件发生更动后重新执行,这就是我们所谓的“回归测试”。
原则8 :计划测试工作时不应默许假定不会发现错误。
项目经理经常容易犯这个错误,这也是使用了不正确的测试定义的一个迹象—
也就是说,假定“测试是一个证明程序正确运行的过程”。我们再一次重申,所谓
测试,就是为发现错误而执行程序的过程。
原则9:程序某部分存在更多错误的可能性,与该部分已发现错误的数量成正比。
这种现象如图2…2所示。乍看上去,这幅图似乎没有什么意义,但很多程序都
存在这种现象。例如,假如某个程序由两个模块、类或子程序A和B组成,模块A
中已经发现了五个错误,而模块B 中仅仅找到了一处错误。如果模块A所经过的测
试并不是故意设计得更为严格,那么该原则告诉我们,模块A 与模块B相比,存在
更多错误的可能性要大。
…………………………………………………………Page 26……………………………………………………………
14 软件测试的艺术
性
能
可
的
误
错
存
残
已知错误的数量
图2…2 残存错误与已知错误间令人惊奇的联系
该原则的另一个说法是,错误总是倾向于聚集存在,而在一个具体的程序中,某
些部分要比其他部分更容易存在错误,尽管没有人能够对这种现象给出很好的解释。
这种现象之所以有用,是因为它给予了我们对软件测试过程的深入理解或反馈信息。
如果一个程序的某个部分远比其他部分更容易产生错误,那么这种现象告诉我们,为
了使测试获得更大的成效,最好对这些容易存在错误的部分进行额外的测试。
原则10:软件测试是一项极富创造性、极具智力挑战性的工作。
测试一个大型软件所需要的创造性很可能超过了开发该软件所需要的创造性。
我们已经看到,要充分地测试一个软件以确保所有错误都不存在是不可能的。本
书后续章节讨论的技术使我们能够为某个软件设计出合理的测试用例集,然而这
些技术仍然需要大量的创造性。
2。4 小结
在阅读本书接下来的内容时,请牢记以下几个重要的测试原则:
o 软件测试是为发现错误而执行程序的过程。
o 尽量避免编码人员测试自己的程序。
o 好的测试用例能够对未发现的错误高度敏感。
o 成功的测试用例能够发现未知的错误。
o 成功的测试需要仔细定义输入输出的期望值。
o 成功的测试需要仔细研究分析测试结果。
…………………………………………………………Page 27……………………………………………………………
第3 章
Chapter 3
代码检查、走查与评审
多年以来,软件界的大多数人都持有一个想法,即编写程序仅仅是为了提供
给机器执行,并不是供人们阅读的,软件测试的惟一方法就是在计算机上执行它。
20世纪70年代早期,一些程序员最先意识到阅读代码对于构成完善的软件测试和
调试手段的价值,通过他们的努力,原有的观念开始发生变化。
今天,并不是所有的软件测试人员都要阅读代码,但是研读程序代码作为测
试工作的一部分,这个观念已经得到了广泛认同。以下几个因素会影响到特定的
测试和调试工作需要人工实际阅读代码的可能性:软件的规模和复杂度、软件开
发团队的规模、软件开发的时限(例如时间安排表是松散还是紧密)等,当然还
有编程小组的技术背景和文化。
基于这些原因,在深入研究较为传统的基于计算机的测试技术之前,我们首
先讨论非基于计算机测试的过程(即“人工测试”)。人工测试技术在查找错误方
面非常有效,以至于任何编程项目都应该使用其中的一种或多种技术。应该在程
序开始编码之后、基于计算机的测试开始之前使用这些方法。同样,也可以在编
程过程的更早阶段就开始设计和应用类似的方法(例如在每个设计阶段的末尾),
但是这些内容超出了本书讨论的范围。
在开始讨论人工测试技术之前,有一条重要的注意事项:由于包含了人为因
素在内,导致很多方法的正规性要差于由计算机执行的数学证明,人们可能会
怀疑某些如此简单和不正规的东西是否有用。反之亦然。这些不正规的方法并
没有妨碍测试取得成功;相反,它们从以下两个方面显著地提高了测试的功效
和可靠性。
首先,人们普遍认识到错误发现得越早,改正错误的成本越低,正确改正错
误的可能性也越大。其次,程序员在开始基于计算机的测试时似乎要经历一个心
…………………………………………………………Page 28……………………………………………………………
16 软件测试的艺术
理上的转变。从内部产生的压力似乎会急剧增长,并产生一个趋势,要“尽可能
快地修正这个缺陷”。由于这些压力的存在,程序员在改正某个由基于计算机测试
发现的错误时所犯的失误,要比改正早期发现的问题时所犯的失误更多一些。
3。1 代码检查与走查
代码检查、走查以及可用性测试是三种主要的人工测试方法。这些测试方
法可以应用在软件开发的任何阶段,包括在一个应用程序编码基本结束或者每
一个模块(单元)编码结束之后(阅读第5章关于模块或单元测试的更多内容)。
本章将主要介绍前两种针对代码的(白盒级别的)测试方法。在第7章我们会
讨论可用性测试。
由于代码走查和检查这两种方法具有很多共同之处,所以在这里我们将讨
论它们的相似点,而它们的不同之处将在后续章节中介绍。
代码检查与走查都要求人们组成一个小组来阅读或直观检查特定的程序。无
论采用哪种方法,参加者都需要完成一些准备工作。准备工作的高潮是在参加者
会议上进行的所谓“头脑风暴会”。“头脑风暴会”的目标是找出错误来,但不必
找出改正错误的方法。换句话说,是测试,而不是调试。
代码检查与走查已经广泛运用了很长时间。我们认为,它们的成功与本书第2
章所述的一些原则有关。
在代码走查中,一组开发人员(三到四人为最佳)对代码进行审核。其中
只有一人是代码的作者。因此,代码走查的主要工作是由其他人,而不是作者
本人完成的,这和软件测试的第2 原则,也即“软件编写者往往不能有效地测
试自己的软件”相符合。(参见第2 章,表2。1 ,本书将陆续涉及表中归纳的10
条测试原则。)
代码检查与走查是对过去桌面检查过程(在提交测试前由程序员阅读自己程
序的过程)的改进。与原方法相比,代码检查与走查更为有效,同样是因为在实
施过程中,除了软件编写者本人,还有其他人参与进来。
代码走查的另一个优点在于,一旦发现错误,通常就能在代码中对其进行精
确定位,这就降低了调试(错误修正)的成本。另外,这个过程通常发现成批的
错误,这样错误就可以一同得到修正。而基于计算机的测试通常只能暴露出错误
的某个表症(程序不能停止,或打印出了一个无意义的结果),错误通常是逐个地
…………………………………………………………Page 29……………………………………………………………
第3章 代码检查、走查与评审 17
被发现并得到纠正的。
在典型的程序中,这些方法通常会有效地查找出30%~70% 的逻辑设计和编码
错误。但是,这些方法不能有效地查找出高层次的设计错误,例如在软件需求分
析阶段的错误。请注意,所谓30%~70% 的错误发现率,并不是说所有错误中多达
70%可能会被找出来,而是讲这些方法在测试过程结束时可以有效地查找出多达
70% 的已知错误。请记住,第2章告诉我们,程序中的错误总数始终是未知的。
当然,可能存在对这些统计数字的批评,即人工方法只能发现“简单”的错
误(即与基于计算机的测试方法相比,所发现的问题显得微不足道),而困难的、
不明显的或微妙的错误只能用基于计算机的测试方法才能找到。然而,一些测试
人员在使用了人工方法之后发现,对于某些特定类型的错误,人工方法比基于计
算机的方法更有效,而对于其他错误类型,基于计算机的方法更有效。这就意味
着,代码检查/ 走查与基于计算机的测试是互补的。缺少其中任何一种,错误检查
的效率都会降低。
最后,不但这些测试过程对于测试新开发的程序有着不可估量的作用,而且
对于测试更改后的程序,这些测试过程具有相同的作用,甚至更大。根据我们的
经验,修改一个现存的程序比编写一个新程序更容易产生错误(以每写一行代码
的错误数量计)。因此,除了回归测试方法之外,更改后的程序还要进行这些人工
方法的测试。
3。2 代码检查
所谓代码检查,是以组为单位阅读代码,它是一系列规程和错误检查技术的
集合。对代码检查的大多数讨论都集中在规程、所要填写的表格等。这里对整个
规程进行简短的概述,之后我们将重点讨论实际的错误检查技术。
3。2。1 代码检查小组
一个代码检查小组通常由四人组成,其中一人发挥着协调作用。协调人应该
是个称职的程序员,但不是该程序的编码人员,不需要对程序的细节了解得很清
楚。协调人的职责包括以下几点:
o 为代码检查分发材料、安排进程。
o 在代码检查中起主导作用。
…………………………………………………………Page 30……………………………………………………………
18 软件测试的艺术
o 记录发现的所有错误。
o 确保所有错误随后得到改正。
第二个小组成员是代码的作者。小组中的其他成员通常是程序的设计人员
(如果设计人员不同于编码人员的话),以及一名测试专家。这名测试专家应该
具备较高的软件测试造诣并熟悉大部分的常见编码错误,下文会就这些常见编
码错误进行讨论。
3。2。2 检查议程与注意事项
在代码检查之前的几天,协调人将程序清单和设计规范分发给其他成员。所
有成员应在检查之前熟悉这些材料。在检查进行时,主要进行两项活动:
1。 由程序编码人员逐条语句讲述程序的逻辑结构。在讲述的过程当中,小组
的其他成员应提问题、判断是否存在错误。在讲述中,很可能是程序编码
人员本人而不是其他小组成员发现了大部分错误。换句话说,对着大家大
声朗读程序,这种简单的做法看来是一个非常有效的错误检查方法。
2。 参考常见的编码错误列表分析程序(错误列表将在下一节中介绍)。
协调人负责确保检查会议的讨论高效地进行、每个参与者都将注意力集中于
查找错误而不是修正错误(错误的修正由程序员在检查会议之后完成)。
会议结束之后,程序员会得到一份已发现错误的清单。如果发现的错误太多,
或者某个错误涉及对程序做根本性的改动,协调人可能会在错误修正后安排对程
序进行再次检查。这份错误清单也要进行分析、归纳,用以提炼错误列表,以便
提高以后代码检查的效率。
如上所述,这个代码检查过程通常将注意力集中在发现错误上,而不是纠正错
误。然而,有些小组可能会发现,当检查出某个小问题之后,有两三个人(包括负
责该代码的程序员本人)会建议对设计进行明显的修补以解决这个特例。那么,对
这个小问题的讨论,反过来会将整个小组的注意力集中在设计的某个部分。在探讨
修补设计来解决这个小问题的最佳方法时,有人可能会注意到另外的问题。既然小
组已经发现了设计中同一部分的两个相关问题,那么每隔几段代码就可能需要密集
的注释。几分钟之内,整个设计就被彻底检查完,任何问题都会一目了然。
在代码检查的时间及地点的选择上,应避免所有的外部干扰。代码检查会议
的理想时间应在90~120分钟。由于开会是一项繁重的脑力劳动,会议时间越长效
…………………………………………………………Page 31……………………………………………………………
第3章 代码检查、走查与评审 19
率越低。大多数的代码检查都是按每小时大约阅读150行代码的速度进行。因此,
对大型软件的检查应安排多个代码检查会议同时进行,每个代码检查会议处理一
个或几个模块或子程序。
3。2。3 对事不对人,和人有关的注意事项
请注意,要使检查过程有成效,必须树立正确的态度。如果程序员将代码检
查视为对其人格的攻击、采取了防范的态度,那么检查过程就不会有效果。正确
的做法是,程序员必须怀着非自我本位的态度来对待检查过程,对整个过程采取
积极和建设性的态度:代码检查的目标是发现程序中的错误,从而改进软件的质
量。正因为这个原因,大多数人建议应对代码检查的结果进行保密,仅限于参与
者范围内部。尤其是如果管理人员想利用代码检查的结果,那么就与检查过程的
目的背道而驰了。
3。2。4 代码检查的衍生功效
除了可以发现错误这个主要作用之外,代码检查还有其他的衍生作用。其
一,程序员通常会得到编程风格、算法选择及编程技术等方面的反馈信息。其
二,其他参与者也可以通过接触程序员的错误和编程风格而同样受益匪浅。通
常来说,这种类型的测试方法能够增强项目中团队的凝聚力,减少消极人际关
系滋长的可能性,有利于打造高度合作的、高效的以及信得过的开发模式。
(要辩证看待码检查的这些功效,一旦没有做好出现像前面提到的人身攻击之
类的事情,则造成恶劣影响,所以进行代码检查一定要准备充分且不断摸索成
功经验,摈弃不好的实践。—译者注)
最后还有,代码检查是能够在早期发现程序中脆弱部位的方法之一,有助
于在测试过程中将更多的注意力集中在这些脆弱地方(与第2章第9条测试原则
不谋而合)。
3。3 用于代码检查的错误列表
代码检查过程的一个重要部分就是对照一份错误列表,来检查程序是否存在
常见错误。遗憾的是,有些错误列表更多地注重编程风格而不是错误(例如,“注
释是否准确且有意义?”,“if…else代码段和do…while代码段是否缩进对
…………………………………………………………Page 32……………………………………………………………
20 软件测试的艺术
齐?”),错误检查太过模糊而实际上没有用(例如,“代码是否满足设计需求?”)。
本节中讨论的错误列表是经多年对软件错误的研究编辑而成的。该错误列表在很
大程度上是独立于编程语言的,也就是说,大多数的错误都可能出现在用任意语
言编写的程序中。读者可以把自己使用的编程语言中特有的错误,以及代码检查
发现的错误补充到这份错误列表中去。
3。3。1 数据引用错误
1。 是否有引用的变量未赋值或未初始化?这可能是最常见的编程错误,在各
种环境中都可能发生。在引用每个数据项(如变量、数组元素、结构中的
域)时,应试图非正式地“证明”该数据项在当前位置具有确定的值。
2。 对于所有的数组引用,是否每一个下标的值都在相应维规定的界限之内?
3。 对于所有的数组引用,是否每一个下标的值都是整数?虽然在某些语言中
这不是错误,但这样做是危险的。
4。 对于所有的通过指针或引用变量的引用,当前引用的内存单元是否分配?
这就是所谓的“虚调用”(dangling reference )错误。当指针的生命期大于
所引用内存单元的生命期时,错误就会发生。当指针引用了过程中的一个
局部变量,而指针的值又被赋给一个输出参数或一个全局变量,过程返回
(释放了引用的内存单元)结束,尔后程序试图使用指针的值时,这种错误
就会发生。与前面检查错误的方法类似,应试图非正式地“证明”,对于每
个使用指针值的引用,引用的内存单元都存在。
5。 如果一个内存区域具有不同属性的别名,当通过别名进行引用时,内存区
域中的数据值是否具有正确的属性?在FORTRAN语言中对EQUIVALENCE
语句使用,或COBOL语言中对REDEFINES语句使用的地方,都可能发生
这种错误。例如,一个FORTRAN语言程序包含一个实型变量A和一个整型
变量B ,两
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!