测试是所有工程学科的基本组成单元。对于软件工程而言,软件测试是软件开发的重要组成部分,是软件工程的重要分支。软件测试是确保软件质量的重要一环,测试是手段,质量是目的,属于软件工程领域。自程序设计起,测试就一直伴随着。为了保证软件产品的质量,软件测试工作越来越重要,测试对于软件生产来说是必需的,问题是我们应该思考采用什么方法?如何安排测试?
软件测试是伴随着软件的产生而产生的。
早期的软件开发过程中,那时软件规模都很小、复杂程度低,软件开发的过程混乱无序、相当随意,测试的含义比较狭窄,开发人员将测试等同于调试,目的是纠正软件中已经知道的故障,常常由开发人员自己完成这部分工作。对测试的投入极少,测试介入也晚,常常是等到形成代码,产品已经基本完成时才进行测试。
直到 1957 年,软件测试才开始与调试区别开来,作为一种发现软件缺陷的活动。由于一直存在着“为了让我们看到产品在工作,就得将测试工作往后推一点”的思想,潜意识里对测试的目的就理解为“使自己确信产品能工作”。测试活动始终后于开发的活动,测试通常被作为软件生命周期中最后一项活动而进行。当时也缺乏有效的测试方法,主要依靠“错误推测Error Guessing”来寻找软件中的缺陷。因此,大量软件交付后,仍存在很多问题,软件产品的质量无法保证。
在软件工程建立之前的 20 世纪 60 年代,软件测试是为表明程序正确而进行的测试。
到了 20 世纪 70 年代,这个阶段开发的软件仍然不复杂,但人们已开始思考软件开发流程的问题,尽管对软件测试的真正含义还缺乏共识,但这一词条已经频繁出现,一些软件测试的探索者建议在软件生命周期的开始阶段就根据需求制定测试计划,这时也涌现出一批软件测试的宗师,Bill Hetzel博士就是其中的领导者。
20 世纪 80 年代早期,质量的号角开始吹响,各个软件企业开始建立QA、SQA部门及其演化流程,软件测试的定义发生了改变。测试不单纯是一个发现错误的过程,而且包含软件质量评价的内容,人们制定了各类标准。
20 世纪 80 年代后期,Paul Rook提供了著名的软件测试V模型,旨在改进软件开发的效率和效果。从此,软件测试模型与软件测试标准的研究也随着软件工程的发展而越来越深入。
20 世纪 90 年代,测试工具盛行起来。
1996 年提出了测试能力成熟度模型(TCMM)、测试支持度模型(TSM)、测试成熟度模型(TMM)。
到了 2002 年,Rick和Stefan在《系统的软件测试》一书中对软件测试做了进一步定义:测试是为了度量和提高被测软件的质量,对测试软件进行工程设计、实施和维护的整个过程。
软件测试的定义:
Bill Hetzel博士的软件测试定义:软件测试的定义最早在 1973 年提出来的。他认为软件测试的目的是建立一种信心,认为程序能够按预期的设想运行。后来在 1983 年他又将定义修订为:评价程序和系统的属性或功能,并确定它是否达到预期的结果。软件测试就是以此为目的的各种行为。在他的定义中,“预期的结果”其实就是我们现在所说的用户需求或功能设计。他还把软件的质量定义为符合要求。他的思想的核心观点是:测试方法是试图验证软件是工作的,即软件的功能是安装预先的设计执行的,以正向思维,针对软件系统的所有功能点,逐个验证正确性。软件测试业界把这种方法看作软件测试的第一类方法。
Geenford Myers的软件测试定义:他认为测试不应该着眼于验证软件是工作的,相反应该首先认定软件是有错误的,然后用逆向思维去发现尽可能多的错误。他对软件测试的定义:测试是为了发现错误而执行的一个程序或系统的过程。
Myers提出的测试的目的推翻了过去为表明软件正确而进行测试的错误认识,为软件测试的发展指出了方向,软件测试的理论、方法在之后得到了长足的发展。第二类软件测试方法在业界也很流行,受到很多学术界专家的支持。
总的来说,第一类测试可以简单抽象地描述为这样的过程:在设计规定的环境下运行软件的功能,将其结果与用户需求或设计结果相比较,如果相符,则测试通过,如果不相符,则视为BUG。这一过程的终极目标是将软件的所有功能在所有设计规定的环境下全部运行并通过。
而第二类测试方法与需求和设计没有必然的关联,更强调测试人员发挥主观能动性,用逆向思维方式,不断思考开发人员理解的误区、不良的习惯、程序代码的边界、无效数据的输入以及系统各种的弱点,试图破坏系统、摧毁系统,目标就是发现系统中各种各样的问题。这种方法往往能够发现系统中存在的更多缺陷。
到了 20 世纪 80 年代初期,软件和IT行业开始了大发展,软件趋向大型化、高复杂度,软件的质量越来越重要。这个时候,一些软件测试的基础理论和实用技术开始形成,并且人们开始为软件开发设计了各种流程和管理方法,软件开发的方式也逐渐由混乱无序的开发过程过渡到结构化的开发过程。
事实上,从广义上讲,软件测试是指软件产品生命周期内所有的检查、评审和确认活动,如设计评审、系统测试;从狭义上讲,软件测试是对软件产品质量的检验和评价。它一方面检查软件产品中存在的质量问题,同时对产品质量进行客观的评价。基于这些认识,我们可以给出软件测试的含义:软件测试就是在软件投入运行前,对软件需求分析、设计规格说明和编码的最终复查,是软件质量保证的关键步骤。
用户普遍希望通过软件测试暴露软件中隐藏的错误和缺陷,以考虑是否可接受该产品;软件开发者则希望测试成为表明软件产品中不存在错误的过程,验证该软件已正确地实现了用户的需求,确立人们对软件质量的信心。
早期人们做测试,所期望达到的目的有几点:测试是程序的执行过程,目的在于发现错误;一个好的测试用例在于能发现至今尚未发现的错误;一次成功的测试是发现了至今尚未发现的错误的测试。
软件测试的目的大家都能随口说出,如查找程序中的错误、保证软件质量、检验软件是否符合客户需求等。这些都对,但他们只是笼统地对软件测试目的进行了概括,比较片面。结合软件开发、软件测试与客户需求可以将软件测试的目的归纳为以下几点:
①对于软件开发来说,软件测试通过找到的问题缺陷帮助开发人员找到开发过程中存在的问题,包括软件开发的模式、工具、技术等方面存在的问题与不足,预防下次缺陷的产生。
②对于软件测试来说,使用最少的人力、物力、时间等找到软件中隐藏的缺陷,保证软件的质量,也为以后软件测试积累丰富的经验。
③对于客户需求来说,软件测试能够检验软件是否符合客户需求,对软件质量进行评估和度量,为客户评审软件提供有力的依据。
当前关于软件测试目的的几种观点:
①软件测试的目的是尽可能发现并改正被测试软件中的错误,提高软件的可靠性。
②软件测试的目的就是保证软件质量。
软件测试一般要达到的具体目标:
①确保产品完成了它所承诺或公布的功能,并且所有用户可以访问到的功能都有明确的书面说明。
②确保产品满足性能和效率的要求。
③确保产品是健壮的且适应用户环境。
软件测试经过几十年的发展,测试界提出了很多软件测试的基本原则,为测试管理人员和测试人员提供了测试指南。软件测试原则非常重要,测试人员应该在测试原则指导下进行测试活动。
软件测试的基本原则有助于测试人员进行高质量的测试,尽早、尽可能多地发现缺陷,并负责跟踪和分析软件中的问题,对存在的问题和不足提出疑问和改进,从而持续改进测试过程。
原则 1:测试显示缺陷的存在。
测试可以显示缺陷的存在,但不能证明系统不存在缺陷。测试可以减少软件中存在缺陷的可能性,但即使测试没有发现任何缺陷,也不能证明软件或系统是完全正确的,或者说是不存在缺陷的。
原则 2:穷尽测试是不可能的。
穷尽测试是不可能的,当满足一定的测试出口准则时测试就应当终止。考虑到所有可能输入值和它们的组合,以及结合所有不同的测试前置条件,这是一个天文数字,我们没有可能进行穷尽测试。在实际测试过程中,测试人员无法执行“天文”数字的测试用例。所以说,每个测试都只是抽样测试。因此,必须根据测试的风险和优先级,控制测试工作量,在测试成本、收益和风险之间求得平衡。
原则 3:测试应尽早介入。
根据统计表明,在软件开发生命周期早期引入的错误占软件过程中出现所有错误(包括最终的缺陷)数量的 50%~ 60%。此外,IBM的一份研究结果表明,缺陷存在放大趋势。如需求阶段的一个错误可能会导致N个设计错误,因此,越是测试后期,为修复缺陷所付出的代价就会越大。因此,软件测试人员要尽早地且不断地进行软件测试,以提高软件质量,降低软件开发成本。
原则 4:缺陷的集群性。
Pareto原则表明“80%的错误集中在 20%的程序模块中”,实际经验也证明了这一点。在通常情况下,大多数的缺陷只是存在于测试对象的极小部分中。缺陷并不是平均而是集群分布的。因此,如果在一个地方发现了很多缺陷,那么通常在这个模块中可以发现更多的缺陷。因此,测试过程中要充分注意错误集群现象,对发现错误较多的程序段或者软件模块,应进行反复的、深入的测试。
原则 5:杀虫剂悖论。
杀虫剂用得多了,害虫就有免疫力,杀虫剂就发挥不了效力。在测试中,同样的测试用例被一遍一遍反复使用时,发现缺陷的能力就会越来越差。这种现象的主要原因在于测试人员没有及时更新测试用例,同时对测试用例及测试对象过于熟悉,形成思维定式。
为克服这种现象,测试用例需要经常评审和修改,不断增加新的不同的测试用例来测试软件或系统的不同部分,保证测试用例永远是最新的,即包含着最后一次程序代码或说明文档的更新信息。这样,软件中未被测试过的部分或者先前没有被使用过的输入组合就会重新执行,从而发现更多的缺陷。同时,作为专业的测试人员,要具有探索性思维和逆向思维,而不仅仅是做输出与期望结果的比较。
原则 6:测试活动依赖于测试内容。
项目测试相关的活动依赖于测试对象的内容。对于每个软件系统,比如测试策略、测试技术、测试工具、测试阶段以及测试出口准则等的选择,都是不一样的。同时,测试活动必须与应用程序的运行环境和使用中可能存在的风险相关联。因此,没有两个系统可以以完全相同的方式进行测试。比如,对关注安全的电子商务系统进行测试,与一般的商业软件测试的重点是不一样的,它更多关注的是安全测试和性能测试。
原则 7:没有失效不代表系统是可用的。
系统的质量特征不仅包括功能性要求,还包括很多其他方面的要求,比如稳定性、可用性、兼容性等。假如系统无法使用,或者系统不能完成客户的需求和期望,那么,这个系统的研发是失败。同时在系统中发现和修改缺陷也是没有任何意义的。
在开发过程中,用户的早期介入和接触原型系统就是为了避免这类问题的预防性措施。有时候,可能产品的测试结果非常完美,可最终的客户并不买账。因为,这个开发角度完美的产品可能并不是客户真正想要的产品。
原则 8:测试的标准是用户的需求。
提供软件的目的是帮助用户完成预定的任务,并满足用户的需求。这里的用户并不特指最终软件测试使用者。比如,我们可以认为系统测试人员是系统需求分析和设计的客户。软件测试的最重要的目的之一是发现缺陷,因此,测试人员应该在不同的测试阶段站在不同用户的角度去看问题,系统中最严重的问题是那些无法满足用户需求的错误。
原则 9:尽早定义产品的质量标准。
只有建立了质量标准,才能根据测试的结果,对产品的质量进行分析和评估。同样,测试用例应该确定期望输出结果。如果无法确定测试期望结果,则无法进行检验。必须用预先精确对应的输入数据和输出结果来对照检查当前的输出结果是否正确,做到有的放矢。
原则 10:测试贯穿于整个生命周期。
由于软件的复杂性和抽象性,在软件生命周期的各个阶段都可能产生错误,测试的准备和设计必须在编码之前就开始,同时为了保证最终的质量,必须在开发过程的每个阶段都保证其过程产品的质量。因此不应当把软件测试仅仅看作是软件开发完成后的一个独立阶段的工作,应当将测试贯穿于整个生命周期始末。
软件项目一启动,软件测试就应该介入,而不是等到软件开发完成。在项目启动后,测试人员在每个阶段都应该参与相应的活动。或者说每个开发阶段,测试都应该对本阶段的输出进行检查和验证。比如在需求阶段,测试人员需要参与需求文档的评审。
原则 11:第三方或独立的测试团队。
由于心理因素,人们潜意识都不希望找到自己的错误。基于这种思维定式,人们难于发现自己的错误。因此,由严格的独立测试部门或者第三方测试机构进行软件测试将更客观、公正,测试活动也会达到更好效果。
软件开发者应尽量避免测试自己的产品,应由第三方来进行测试,当然开发者需要在交付之前进行相关的自测。测试是带有破坏性的活动,开发人员的心理状态会影响测试的效果。同时对于需求规格说明的理解产生的错误,开发人员自己很难发现。
但是,第三方或者独立的测试团队这个原则,并不是认为所有的测试完全由他们来完成。一定程度的独立测试(可以避免开发人员对自己代码的偏爱),可以更加高效地发现软件缺陷和软件存在的失效。但独立测试不是完全的替代物,因为开发人员也可以高效地在他们的代码中找出很多缺陷。在软件开发的早期,开发人员对自己的工作产品进行认真的测试,这也是开发人员的一个职责之一。