第3章
软件测试的实质
第1章“软件测试的背景”和第2章“软件开发的过程”讲述了软件测试和软件开发过程的基础知识。这两章的内容从较高的层面和分析推论的角度描述了软件项目如何运作。遗憾的是,在现实生活中,几乎看不到任何纯粹采用某种模式进行的项目,看不到完全符合客户要求的详细产品说明书,也没有足够的时间去做所有需要做的测试。没有,真的没有。但是,要想成为卓有成效的软件测试员,就应该知道这个理想的过程正是追求的目标。
本章的目的是从软件的角度把这个理想变得现实一点。这将有助于理解在整个开发周期中,实际上必须做出取舍和让步。大多数取舍与软件测试的投入相关,测试中发现的缺陷和避免的问题都对项目有莫大的影响。学完本章后,就会清楚地了解软件测试的作用、影响和责任,从而喜欢上制作软件产品所必需的幕后决策工作。
本章重点包括:
- 软件为什么永远不会完美
- 软件测试为什么不仅仅是技术问题
- 软件测试员的常用术语
3.1 测试的原则
本节所列举的是一些原则或者公理,可以视为软件测试和软件开发的“交通规则”或者“生活常识”。每一条原则对于透彻了解整个过程来说都是宝贵的点滴知识。
3.1.1 完全测试程序是不可能的
软件测试新手可能认为,可以在拿到软件后进行完全测试,找出所有的软件缺陷,确保软件完美无缺。遗憾的是,这是不可能的,即使最简单的程序也不行,主要有如下4个原因:
- 输入量太大。
- 输出结果太多。
- 软件执行路径太多。
- 软件说明书是主观的,可以说从旁观者来看是缺陷。
以上这些“太多”的可能性加在一起,构成了一个太大而难以进行的测试条件。如果不信,那就以如图3-1所示的Microsoft Windows计算器程序为例来看一下。
假设我们受命测试这个计算器。我们决定首先从加法开始。试着输入1+0=,得到的答案是1,结果正确。接着输入1+1=,答案是2。还要走多远呢?因为计算器可以处理32位的数字,所以必须测试所有的可能性,直至输入
1+99999999999999999999999999999999=
这一系列测试完之后,继续输入2+0=、2+1=、2+2=,以此类推。最后输入
99999999999999999999999999999999+99999999999999999999999999999999=
下一步测试所有的小数:1.0+0.1、1.0+0.2,以此类推。
验证完正常的数字相加正确无误之后,还要测试非法输入是否得到正确的处理。不要忘了,不仅可以单击画面上的数字键—还可以按键盘上的任意键。好的测试数据如1+a,z+1,1a1+2b2,…,逐项下来,这样的组合何止亿万。
输入的编辑修改也必须测试。Windows计算器程序允许输入退格键和删除键,应该加以测试。1<退格键>2+2应该等于4。前面测试过的每一项测试还要逐个按退格键重新测试。
如果要测试所有的情况,还得进行3个数相加、4个数相加,等等。
输入项太多了,根本无法完全测试,即使使用超级计算机来输数也无济于事。这还仅仅是加法,还有减法、乘法、除法、求平方根、百分数和倒数等测试要做。
举这个例子的目的是说明完全测试一个程序是不可能的,即使是简单如计算器这样的软件也不例外。如果觉得某些测试条件是重复的、无必要的,或者为了节省空间,而将其剔除,那么采用的就是不完全测试。
3.1.2 软件测试是有风险的行为
如果决定不去测试所有的情况,那就是选择了冒险。在计算器的例子中,如果选择不去测试1024+1024=2048会怎样呢?有可能程序员碰巧在这种情况下留下一个软件缺陷。如果软件测试员没有对此测试,客户却碰巧输入了这组数,就会发现这个缺陷。这将是修复代价很高的软件缺陷,因为它直到软件使用时才被客户发现。
这样说有些耸人听闻。软件测试员不能做全部的测试,不完全测试又会漏掉软件缺陷。软件终归要发布的,所以测试需要停止,但是如果过早停下来,就还有地方没测试到。怎么办?
软件测试员要学会的一个关键思想是,如何把数量巨大的可能测试减少到可以控制的范围,以及如何针对风险做出明智的抉择,哪些测试重要,哪些不重要。
图3-2说明了测试量和发现的软件缺陷数量之间的关系。如果试图测试所有情况,费用将大幅增加,而软件缺陷漏掉的数量在到达某一点后没有显著变化。如果减少测试或者错误地确定测试对象,虽然费用很低,但是会漏掉大量软件缺陷。我们的目标是找到最优的测试量,使测试不多不少。
第4章到第7章将讲述如何设计和选择测试用例以减少风险、优化测试的技术。
3.1.3 测试无法显示潜伏的软件缺陷
好好思考一下这个标题。假设你是负责检查房间是否有害虫的检疫员,通过仔细检查,发现了害虫的迹象—有活的、死的,或者在窝里,你可以肯定地说房间里有害虫。
现在又来到另一个房间。这一次没有找到害虫的迹象。在所有可能的地方找了,找不到害虫出没的痕迹。也许找到一些死虫或者废弃的窝,但是无法证实有活的害虫。你能肯定地说这间房子没有害虫吗?不能,你能得出的结论只是在你的搜索下没有找到活着的害虫。除非在把房子彻底拆掉,否则难以保证不会使其轻易漏网。
软件测试工作与防疫员的工作极为相似,可以报告软件缺陷存在,却不能报告软件缺陷不存在。你可以进行测试,发现并报告软件缺陷,但是任何情况下都不能保证软件缺陷没有了。唯一的方法是继续测试,可能还会找到一些。
3.1.4 找到的软件缺陷越多,就说明软件缺陷越多
生活中的害虫和软件缺陷几乎完全一样。两者都成群出现,发现一个,附近就可能会有一群。
通常,软件测试员会在很长时间内找不到软件缺陷。接着找到一个,之后很快就会接二连三地找到更多。其中的原因是:
- 程序员也有心情不好的时候。和我们大家一样,程序员也要休假。某天编写代码可能心情还不错,另一天可能就烦躁不安了。一个软件缺陷表明很可能附近还有更多的软件缺陷。
- 程序员往往犯同样的错误。每个人都有习惯,一个程序员总是反复犯下自己容易犯的错误。
- 某些软件缺陷实乃冰山一角。软件的设计或者体系常常会出现基本问题。软件测试员可能会发现某些软件缺陷开始似乎毫无关联,但是最后才知道它们是由一个严重的主要原因造成的。
一定要注意,“软件缺陷一个接一个”的说法倒过来讲也对。如果无论如何努力都找不出软件缺陷,那么也可能是软件经过精心编制,确实存在极少的软件缺陷。
3.1.5 杀虫剂怪事
1990年,Boris Beizer在其编著的《Software Testing Techniques》第2版中杜撰了“杀虫剂怪事”一词,用于描述软件测试越多,其对测试的免疫力越强的现象。这与农药杀虫是一样的(见图3-3),总是用一种农药,害虫最后就有了抵抗力,农药再也发挥不了效力。
还记得第2章描述的软件开发螺旋模式吗?每一圈都要重复测试过程。每一次循环,软件测试员都要对软件进行测试。最后,经过几个回合之后,能发现的软件缺陷都发现了,再测试下去也不会有新的发现了。
为了克服杀虫剂怪事,软件测试员必须不断编写不同的、新的测试程序,对程序的不同部分进行测试,以找出更多软件缺陷。
3.1.6 并非所有软件缺陷都要修复
在软件测试中令人沮丧的是,虽然测试员尽了最大的努力,但并非找出的所有软件缺陷都要修复。不要泄气—这并不意味着软件测试员未达到目的,或者项目小组将发布质量欠佳的产品。其真正的含义要依赖第1章所列的软件测试员的素质—进行良好的判断,搞清楚在什么情况下不能追求完美。项目小组需要进行取舍,根据风险决定哪些缺陷要修复,哪些不需要修复。
不需要修复软件缺陷的原因有几个:
- 没有足够的时间。在任何一个项目中,通常是软件功能太多,而代码编写人员和软件测试员太少,而且进度中没有留出足够的时间来完成项目。例如你在制作税务处理程序,4月15日(赶在应付税务检查之前—译者注)是不可更改的交付期限—必须按时完成软件。
- 不算真正的软件缺陷。也许有人会说:“这不算软件缺陷,而是一项功能。”很多情况下,理解错误、测试错误或者说明书变更会把可能的软件缺陷当作功能来对待。
- 修复的风险太大。遗憾的是,这些情形很常见。软件本身是脆弱的,难以厘清头绪,有点像一团乱麻,修复一个软件缺陷可能导致其他软件缺陷出现。在紧迫的产品发布进度压力下,修改软件将冒很大的风险。不去理睬已知的软件缺陷,以避免造成新的、未知的缺陷的做法也许是安全之道。
- 不值得修复。虽然有些不中听,但却是事实。不常出现的软件缺陷和在不常用功能中出现的软件缺陷是可以放过的,可以躲过以及用户有办法预防或避免的软件缺陷通常不用修复。这些都要归结为商业风险决策。
决策过程通常由软件测试员、项目经理和程序员共同参与。他们站在各自的立场看待缺陷,对软件缺陷是否应该或不应该修复都有自己的观点和看法。第19章“报告发现的问题”将详细讲述如何报告软件缺陷,并使其他人知道。
做出错误决策的后果
还记得第1章描述的英特尔奔腾处理器缺陷吗?英特尔公司的测试工程师虽然在芯片发布之前发现了缺陷,但是产品开发小组认为这是一个不常见的小缺陷,不值得修复。他们处于紧张的进度催促之下,决定赶在最后期限之前完工,然后在后面发布的芯片中修复缺陷。结果软件缺陷被发现,后来成了历史事件。
在任何一个软件中,与每一个成为新闻头条的“奔腾处理器”之类的缺陷类似,可能会有数以百计的缺陷没有修复,因为这些缺陷被认为没有大的副作用。只有时间才能告诉我们这样的决策是对的还是错的。
3.1.7 什么时候才叫缺陷难以说清
如果软件中存在问题,但没有人发现—程序员没有发现,测试员没有发现,甚至客户也没有发现—那么它算不算软件缺陷?
假如把一群软件测试员聚集起来提出上述问题,就会引发激烈的讨论。每个人都有自己的观点,都能完美地表达出来。问题是没有准确的答案,答案因开发小组决定的最适合自己的而千差万别。
鉴于本书的目的,回顾一下第1章所述的软件缺陷定义规则:
1)软件未实现产品说明书要求的功能。
2)软件出现了产品说明书指明不应该出现的错误。
3)软件实现了产品说明书未提到的功能。
4)软件未实现产品说明书虽未明确提及但应该实现的目标。
5)软件难以理解、不易使用、运行速度慢,或者软件测试员认为最终用户会认为不好。
遵守以上这些规则,有助于澄清什么样的软件缺陷才算缺陷这个模棱两可的问题。说软件有没有“某功能”,指的是软件运行时发现有“某功能”或者“缺少某功能”。由于不能报告没有看见的问题,因此,没有看见就不能说存在软件缺陷。
还可以从另外一个角度来思考。两个人对于同一个软件产品的质量持有完全不同的见解并不罕见。也许一个人说该软件的缺陷太多,而另一个人会说该软件很完美。怎么可能都对呢?一定是一个人以某种方式运行软件时暴露了大量软件缺陷,而另一个人没有这样做。
注意:尚未发现或未观察到的软件缺陷只能说是潜在缺陷。
如果没搞明白也不要紧,在软件测试中与同行进行探讨,听听他们的看法。听听别人的意见,验证他们的想法,从而明确自己的观点。请记住这个老问题:“一棵树倒在森林中没有人听见,它发出声音了吗?”
3.1.8 产品说明书从没有最终版本
软件开发者面临一个难题。整个行业变化太快,去年还很先进的产品今年就过时了;同时,软件变得更庞大、更复杂,功能越来越多,导致软件开发周期越来越长。这两种反作用力形成了矛盾,结果导致产品说明书经常变化。
除了紧跟变化没有其他办法。假定我们的产品有一份最后定版的且不得更改的产品说明书。两年按部就班的开发进行到一半时,主要竞争对手发布了一个类似的产品,而且拥有一些我们不具备的、吸引人的功能。是继续按照产品说明书开发,明年发布一个没有竞争力的产品,还是重整人马,重新讨论产品功能,重写产品说明书,开发经过修订的产品呢?明智的选择是后者。
软件测试员必须要想到产品说明书可能改变。未曾计划测试的功能会增加,经过测试并报告软件缺陷的功能可能发生变化甚至被删除。这些都是有可能会发生的。本书后面的章节将讲述灵活地制定测试计划和执行测试的技术。
3.1.9 软件测试员在产品小组中不受欢迎
还记得软件测试的目标吗?
软件测试的目标是尽可能早地找出软件缺陷,确保其得以修复。
软件测试员的工作是检查和批评同事的工作,挑毛病,公布发现的问题。唉,做这项工作不会普遍受欢迎的!
下面是保持小组成员和睦的建议:
- 早点找出缺陷。这是软件测试员理所当然的工作,但是做到很难。在三个月之前而不是在产品即将发布前夕找出严重的软件缺陷,会产生更小的影响,更容易让人接受。
- 控制情绪。诚然,软件测试员真心喜爱自己的工作,当发现严重的软件缺陷时非常兴奋。但是,如果兴冲冲地闯进程序员同事的房间告诉他程序代码中存在可怕的缺陷,他是不会高兴的。
- 不要总是报告坏消息。假如发现某段代码没有软件缺陷,就大声宣扬。花一点时间找程序员聊聊天。如果总是报告坏消息,别人对你就会唯恐避之不及。
3.1.10 软件测试是一个讲究条理的技术职业
以前,软件测试是事后考虑的。那时,软件产品很小,也不复杂,使用计算机软件的人数不多。项目小组中几乎没有程序员去相互交叉调试对方的代码。软件缺陷还不是很大的问题,即使出现了,也很容易修复,付出不了多少代价,且不会带来多大的破坏性。即便有软件测试员,也是没受过什么训练的,只是在项目后期“乱搞代码看能发现什么”。但是现在,时代变了。
在软件招聘广告上可以找到许多招聘测试员的条目,软件行业已经发展到强制使用专业软件测试员的程度了。现在,生产低劣软件的代价太高。
公平地讲,并非所有的公司都使用专业软件测试员。不少计算机游戏和短期开发项目的公司依然采用相当松散的开发模式—常常是大爆炸模式或边写边改模式。但是,大多数软件都采用井然有序的方式开发,把软件测试员当作必不可少的核心小组成员。
这对于软件测试的爱好者无疑是福音。现在软件测试成为一个职业选择—需要训练和规范,而且有发展空间。
3.2 软件测试的术语和定义
本章以软件测试的术语和定义作为本书第一部分的结束,这些术语描述了关于软件开发过程和软件测试的基本概念。因为它们常常被混淆和误用,所以在此一并解释,以帮助读者理解其真实含义和区别。注意,软件行业中对于许多看起来似乎相同的术语很少达成一致认识。软件测试员应该常常澄清小组中使用的术语的含义,最好是在术语定义上取得一致而不是在“正确性”上争论。
3.2.1 精确和准确
软件测试员必须要知道精确(precision)和准确(accuracy)之间的区别。假如对计算器进行测试,你会测试返回结果是精确的还是准确的呢?或者两者都测试?如果项目进度迫使只能进行二选一的抉择呢?
测试的软件假如是棒球或模拟飞行之类的模拟游戏程序又怎样?主要测试精确度还是准确度?
图3-4用图示方法描述了这两个术语。飞镖游戏的目标是设法投中靶盘的中心区域。左上角靶盘上的飞镖既不精确也不准确。它们不仅远离靶心,而且相互之间分得很开。
右上角靶盘上的飞镖精确但不准确。它们紧紧地聚在一起,因此可以说投掷者有很高的稳定性,但是不够准确,因为飞镖全部脱靶。
左下角靶盘上的飞镖是准确但不精确的例子,因为飞镖非常接近靶心,因此可以说投掷者非常接近瞄准的目标,但飞镖落点分散,谈不上稳定性。
右下角靶盘上的飞镖是精确和准确的完美结合。飞镖落点集中而且命中目标。
软件测试要精确度还是准确度很大程度上取决于产品是什么,最终取决于开发小组的目标(请恕我直言)。计算器软件需要两者都达到—正确的答案就是正确的答案,错误的就是错误的。但是,可能会决定计算只精确到五位十进制数,那么,精确度可以有所偏差。只要软件测试员清楚产品说明书,就可以量身定制测试程序来确认。
3.2.2 确认和验证
虽然确认(verification)和验证(validation)常常互换使用,但是它们有不同的定义,其中的区别对软件测试很重要。
确认是保证软件符合产品说明书的过程;验证是保证软件满足用户要求的过程。尽管它们听起来很相似,然而通过对哈勃(Hubble)天文望远镜问题的分析就可以澄清这两者的区别。
1990年4月,哈勃天文望远镜被发射到地球轨道。它是一个反射望远镜,主要利用一面巨大的镜子来放大观察的目标。建造这面镜子是一项精确度和准确度要求极其严格的艰巨任务。镜子的测试极其困难,因为望远镜被设计用于太空,在地球上无法固定甚至全面观察。因此唯一的测试方法是仔细度量其全部属性,并将度量结果和规定数值进行比较。进行上述测试之后,哈勃天文望远镜被宣称可以发射了。
不幸的是,哈勃太空望远镜投入使用不久发现,它传回来的图像没有正确聚焦。调查发现镜子制造出了问题。镜子虽然根据产品说明书进行了表面处理,但是产品说明书是错的。结果虽然镜子精确度极高,但准确度不够。测试虽然保证镜子符合产品说明—确认,但是不能保证满足最初的需求—验证。
1993年,通过航天飞机来修正哈勃太空望远镜,安装了一个“校正镜头”装置重新校准由制造不合格的镜子生成的图像。
虽然这不是软件的例子,但是确认和验证同样适用于软件测试。绝对不能假定产品说明书是对的,如果确认了产品说明书并对最终产品进行验证,就有望避免类似哈勃太空望远镜的问题。
3.2.3 质量和可靠性
韦氏电子词典把质量(quality)定义为“优秀程度”或者“同类优越性”。如果说软件产品质量高,就是指它能够满足客户要求。客户会感到该产品性能卓越,优于其他产品。
软件测试员常常会错误地以为质量和可靠性是一回事。他们认为如果测试程序一直稳定、可靠,就可以认定这是高质量的产品。遗憾的是,这不完全正确。可靠性仅仅是质量的一个方面。
软件使用者心目中的质量可能包括:软件功能的多少、在自己的旧PC上运行的能力、软件公司的服务电话好不好打以及软件的价格。产品的可靠性或者产品多长时间崩溃的问题也许重要,但常常不被考虑到。
为了确保程序质量高而且可靠性强,软件测试员必须在整个产品开发过程中进行确认和验证。
3.2.4 测试和质量保证
最后一对定义是测试(testing)和质量保证(Quality Assurance,QA)。这两个术语经常用于描述确认和验证的小组和过程。第21章“软件质量保证”将详细讲述质量保证。现在请看以下定义:
- 软件测试员的目标是尽可能早地找出软件缺陷,并确保缺陷得以修复。
- 软件质量保证人员的主要职责是创建和执行改进软件开发过程并防止软件缺陷发生的标准和方法。
当然,它们存在一些交叉之处。软件测试员会做一些QA工作,QA人员会进行一些测试,双方的工作和任务是交织在一起的。重要的是了解自己的工作职责,并与开发小组的其他成员交流。小组成员如果搞不清楚谁在做测试谁不在做测试的话,将会给许多项目带来不少麻烦。
##小 结
香肠、法律和软件—它们的制造过程都很繁杂。但愿前三章没有吓着你。
许多参与项目的软件测试员不清楚周围发生的事情,不清楚如何做出决定,或者不清楚应该遵照什么过程,这样是不可能有太多成效的。截至目前,学习了软件测试和软件开发过程方面的知识之后,在开始进行测试时就会有一个良好的开端。你将了解自己扮演的角色,至少知道提出哪些问题才能找到自己的位置。
到目前为止,关于过程的所有内容已经讲完了。下一章将进入新的部分,介绍软件测试的基本技术。
##小测验
以下是帮助读者加深理解的小测验。答案参见附录A—但是不要偷看!
- 假定无法完全测试某一程序,在决定是否应该停止测试时要考虑哪些问题?
- 启动Windows计算器程序,输入5,000–5=(逗号不能少),观察结果。这是软件缺陷吗?为什么?
- 假如测试模拟飞行或模拟城市之类的模拟游戏,精确度和准确度哪一个更值得测试?
- 有没有质量很高但可靠性很差的产品?请举例说明。
- 为什么不可能完全测试程序?
- 假如周一测试软件的某一功能,每小时发现一个新的软件缺陷,你认为周二将会以什么样的频率发现软件缺陷?