1
 软件工程
1.7.2.1 5.2.1 软件测试的基本概念

5.2.1 软件测试的基本概念

1.软件测试的目的

软件开发项目在经历了计划、需求分析、设计和编码以后,已经取得了一些阶段性成果,但是这些阶段性成果能不能真正满足用户提出的需求,或者说它能在多大程度上满足用户的需求,这是软件人员、管理人员及用户都十分关心的问题。因为,大量的人力、物力投入了开发工作,又经历了阶段复审,人们迫切希望拿到合格的成果。这时,一系列的质量检验活动显然变成非常必要了。

软件开发项目的大量实践表明,这些“成果”常常是很不理想的。仅以编写出源程序为例,可能遇到许多情况。

(1)程序编写得无语法错误。这是程序编写是否正确的最基本要求。我们知道,具有语法错误的程序在上机运行时,无法通过编译系统语法检查这第一关。编译程序会列举出被运行程序的各种语法错误现象,而拒绝编译和执行。

(2)程序执行中未发现明显的运行错误。这是指程序运行过程中没有因过大或过小的数据产生溢出而无法继续执行,也没有因遇到死循环而阻碍运行等情况。

(3)程序中没有不适当的语句。例如,有的变量未经说明而引用,有的虽已作说明却未曾引用,或者有的变量未赋值而引用,以及有的变量被多次赋值而并未引用,等等。

(4)程序运行时,能通过典型的有效测试数据,而得到正确的预期结果,即程序能接收规格说明所规定正常条件下的合理数据,并给出正确结果。

(5)程序运行时能通过典型的无效测试数据,而得到正确的结果,即当程序接收规格说明所规定异常条件下的不合理数据时,能给出恰当的结果。

(6)程序运行时,能通过任何可能的数据,并给出正确的结果。

十分明显,提高程序的正确性就是要尽可能发现和消除程序中隐藏的各种差错。如上所述,编译系统接收用户的源程序后所做的语法检查能发现程序编写时出现的语法错误,但也仅仅是一些语法错误。更多情况的差错编译系统是无法查出的。例如,程序中往往会出现的逻辑性差错、名字拼写错、不正确的初始化或未作初始化、数据格式或文件格式不对、循环次数有错、调用了错误的程序块或纯属语义上的差错,等等。

尽管程序正确性证明作为计算机科学的一个新分支,近年来取得了显著的发展,然而尚未到达实用化阶段。要想解决以上程序中列举的各种问题,目前比较实际的办法只能依靠测试技术。程序测试的目的是为了发现隐藏在程序内部的各种错误,有时也称为Bug。程序测试工作是指为发现程序错误而进行的各种活动。

有人认为,程序测试的目的是为了说明程序是没有问题的。在程序编写完成后,只需找到几个数据,使程序能够通过运行就达到目的了。事实上,这是十分错误的观点。因为,若是出于这一目的,人们会自觉或不自觉地寻找容易使程序通过的测试数据,回避那些易于暴露程序错误的测试数据,致使隐藏的错误不被发现,自然也就得不到排除。与此相反,如果测试活动的目标始终围绕着揭露程序中的错误,那么在选取测试数据时,自然要考虑那些易于发现程序错误的数据。并且认为,能够发现程序错误的数据是好的数据,能够高效揭露程序错误的测试是成功的测试。持相反观点的人必然认为那些是坏的数据,找出程序隐患的测试是失败的测试。

2.软件测试的对象

前面谈到,查找程序中的差错是软件测试工作的目的。但必须注意,软件测试并不等于程序测试。在软件测试阶段我们应该集中精力查找开发项目以来可能发生的各种错误,因此,需求分析、总体设计、详细设计及程序编码等各开发阶段所得到的开发资料,包括需求规格说明、概要设计说明、详细设计说明及源程序都应该是软件测试的对象。软件测试不应仅限于程序测试的狭小范围内,而置其他开发阶段的工作于不顾。还应看到,由于开发工作各阶段是互相衔接的,前一阶段工作中发生的问题如未得到及时解决,很自然会影响到下一阶段。从源程序的测试中找到的程序错误不一定都是因为程序编码阶段造成的。如果简单地把程序中的错误全都归罪于程序员的程序编码,未免会冤枉他们。据统计表明,在查找出的软件错误中,属于需求分析和软件设计的错误约占64%,属于程序编码的错误仅占36%。这就说明,就程序编码而言,它的许多错误是“先天的”。其实,到软件测试时为止,开发工作已经经历了多个环节,每个环节都有可能发生问题。目前我们还没有办法把握这些环节,使之不发生任何差错。在对需求理解和表达的正确性、设计和表达的正确性、实现的正确性及运行的正确性中,任何一个环节上发生了问题都可能在软件测试中表现出来。

3.软件测试的基本原则

(1)完全测试是不可能的。考虑一个实例:Windows系统下的计算器软件,要想对该软件进行完全测试,不仅需要大量的输入,而且输出结果和执行路径也相当多,另外软件说明书的主观性也决定不可能完成这项工作。

(2)软件测试是有风险的活动,如果不选择完全测试所有情况,则选择了冒险。软件测试员此时要做的是如何将数量巨大的可能测试减少到可以控制的范围,并针对风险做出明智的选择,确定哪些软件测试重要,哪些软件测试不重要。

(3)软件测试无法显示隐藏的软件缺陷和故障。软件测试员可以报告软件缺陷存在,却不能报告软件缺陷不存在。进行软件测试,发现并报告软件缺陷,但是任何情况下都不能保证软件缺陷不存在。找到隐藏的软件缺陷和故障的唯一方法是继续软件测试,找到更多的软件缺陷。

(4)充分注意软件测试中的群集现象。软件缺陷可能成群出现,也就是说发现一个缺陷,附近就可能有一群缺陷。造成群集现象的可能原因是:程序员在某一段时间情绪不好;程序员往往犯同样的错误;有些软件缺陷可能只是“冰山一角”。

(5)杀虫剂现象。软件测试越多,对测试的免疫力越强,要想寻找到更多的软件缺陷就越困难。在软件测试中采用单一的方法不能高效和完全地针对所有软件缺陷,因此软件测试应该尽可能多地采用多种途径进行测试。

(6)并非所有的软件缺陷都要修复。软件测试员要对找到的缺陷进行判断,根据风险决定哪些缺陷需要修复,哪些不需要修复。造成软件缺陷不能修复的原因有时间不够,不算真正的软件缺陷,修复的风险太大,不值得修复。

(7)软件测试必须有预期结果。在执行测试程序之前应该对期望的输出有很明确的描述,测试后将程序的输出同预期结果进行对照。若不事先确定预期的输出,可能把似乎是正确而实际是错误的结果当成正确结果。

(8)尽早地、不断地进行软件测试。由于软件具有复杂性和抽象性,使得软件开发的各个环节都可能产生错误。应坚持在软件开发的各个阶段进行技术评审,以尽早发现和预防错误,把出现的错误在早期消除,杜绝某些隐患。在发现错误并进行纠错后,要重新进行软件测试。对软件的修改可能会带来新的错误,不要希望软件测试能一次成功。

(9)程序员应该避免检查自己的程序。软件测试为了尽可能多地发现错误,从某种意义上讲是对程序员工作的一种否定。因此,程序员检查自己的程序会存在一定的心理障碍。而软件测试工作需要严谨的作风、客观的态度和冷静的情绪。另外,由程序员对软件需求说明书理解的偏差而引入的错误则更难发现。如果由别人来测试程序员编写的程序,则会更客观、更有效,并且更容易取得成功。

4.软件测试的基本步骤

软件测试过程按测试的先后次序可分为单元测试、集成测试、确认测试、系统测试和验收测试,如图5-2所示。

img54

图5-2 软件测试过程

1)单元测试

单元测试又称为模块测试,是最小单位的测试,其依据是详细设计描述,对模块内所有重要的控制路径设计测试用例,以便发现模块内部的错误。单元测试多采用白盒测试技术,系统内多个模块可以并行地进行单元测试。

2)集成测试

集成测试又称为组装测试,集成测试是在单元测试的基础上,将所有模块按照设计要求组装成子系统或系统进行的测试活动。

3)确认测试

完成集成测试以后,要对开发工作初期制定的确认准则进行检验。确认测试是检验所开发的软件能否满足所有功能和性能需求的最后手段,通常均采用黑盒测试方法。

4)系统测试

系统测试是将通过确认测试的软件,作为整个应用系统的一个元素,与硬件、支持软件、数据和人员等其他系统元素结合在一起,在实际运行环境下,对系统进行一系列的集成测试和确认测试。系统测试的目的在于通过与系统的需求定义作比较,发现软件与系统定义不符合的地方,以验证软件系统的功能和性能等。

5)验收测试

检验软件产品质量的最后一道工序是验收测试。与前面讨论的各种测试活动的不同之处主要在于它突出了用户的作用,同时软件开发者也应有一定程度的参与。

5.静态方法与动态测试

1)静态方法

静态方法的主要特征是在用计算机测试源程序时,计算机并不真正运行被测试的程序。这说明静态方法一方面要利用计算机作为被测程序进行特性分析的工具,它与人工测试有着根本的区别;另一方面它并不真正运行被测程序,只进行特性分析,这与动态测试是不同的。因此,静态方法常称为静态分析,静态分析是对被测程序进行特性分析的一些方法的总称。

静态分析并不等同于编译系统,编译系统虽然也能发现某些程序错误,但这些错误远非软件中存在的大部分错误,静态分析的查错和分析功能是编译程序所不能代替的。目前已经开发出一些静态分析系统作为软件测试的工具,静态分析已被当做一种自动化的代码校验方法。不同的方法有各自的目标和步骤,侧重点也不一样。常用的静态测试方法如下。

(1)桌前检查:由程序员检查自己的程序,对源代码进行分析、检验。

(2)代码会审:由程序员和测试员组成评审小组,按照“常见的错误清单”进行会议讨论检查。

(3)步行检查:与代码会审类似,也要进行代码评审,但评审过程主要采取人工执行程序的方式,故也称为“走查”。

步行检查是最常用的静态分析方法,进行步行检查时,还常使用以下分析方法:一是调用图,从语义的角度考察程序的控制路线;二是数据流分析图,检查分析变量的定义和引用情况。

2)动态测试

动态测试的主要特征是计算机必须真正运行被测试的程序,通过输入测试用例,对其运行情况(输入/输出的对应关系)进行分析。

动态测试方法与静态分析方法的区别是:需要通过选择适当的测试用例,上机执行程序进行测试。常用的方法是白盒测试和黑盒测试。

无论是白盒测试还是黑盒测试,其关键都是如何选择高效的测试用例。所谓高效的测试用例是指一个用例能够覆盖尽可能多的测试情况,从而提高测试效率。白盒测试和黑盒测试各有自己的优、缺点,它们构成互补关系,在规划测试时需要把白盒测试与黑盒测试结合起来使用。