购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

4.3 软件测试与软件维护

本节将介绍软件测试与软件维护。

4.3.1 软件测试

软件测试是软件质量保证的主要手段之一,也是在将软件交付给客户之前所必须完成的步骤。目前,软件的正确性证明尚未得到根本的解决,软件测试仍是发现软件错误和缺陷的主要手段。

大量统计资料表明,目前软件测试所花费用已超过软件开发费用的30%。

1.软件测试基础
1)软件测试的目的

软件测试的目的就是在软件投入生产性运行之前,尽可能多地发现软件产品(主要是指程序)中的错误和缺陷。

为了发现程序中的错误,应竭力设计能暴露错误的测试用例。测试用例是由测试数据和预期结果构成的。一个好的测试用例是极有可能发现至今为止尚未发现的错误的测试用例。一次成功的测试是发现了至今为止尚未发现的错误的测试。

高效的测试是指用少量的测试用例,发现被测软件尽可能多的错误。

软件测试所追求的目标就是以尽可能少的时间和人力发现软件产品中尽可能多的错误。

2)软件测试准则

● 应该尽早地、不断地进行软件测试,把软件测试贯穿于开发过程的始终。

● 所有测试都应该能追溯到用户需求。从用户的角度看,最严重的错误是导致软件不能满足用户需求的那些错误。

● 应该从“小规模”测试开始,并逐步进行“大规模”测试。

● 应该远在测试之前就制定出测试计划。

● 根据Pareto原理,80%的错误可能出现在20%的程序模块中,测试成功的关键是怎样找出这20%的模块。

● 应该由独立的第三方从事测试工作。

● 对非法和非预期的输入数据也要像合法的和预期的输入数据一样编写测试用例。

● 检查软件是否做了应该做的事仅是成功的一半,另一半是看软件是否做了不该做的事。

● 在规划测试时不要设想程序中不会查出错误。

● 测试只能证明软件中有错误,不能证明软件中没有错误。

3)软件测试分类

● 从测试阶段划分,可分为单元测试、集成测试、确认测试。

● 从测试方法划分,可分为白盒测试、黑盒测试。

在实际应用中,一旦纠正了程序中的错误后,还应选择部分或全部原先已测试过的测试用例,对修改后的程序重新测试,这种测试称为回归测试。

2.单元测试

单元测试(Unit Testing),也称模块测试,通常可放在编程阶段,由程序员对自己编写的模块自行测试,检查模块是否实现了详细设计说明书中规定的功能和算法。单元测试主要发现编程和详细设计中产生的错误,单元测试计划应该在详细设计阶段制定。

单元测试期间着重从以下几个方面对模块进行测试:模块接口、局部数据结构、重要的执行通路、出错处理通路、边界条件等。

测试一个模块时需要为该模块编写一个驱动模块和若干个桩(stub)模块。驱动模块用来调用被测模块,它接收测试者提供的测试数据,并把这些数据传送给被测模块,然后从被测模块接收测试结果,并以某种可以看见的方式(例如显示或打印)将测试结果返回给测试者。桩模块用来模拟被测模块所调用的子模块,它接受被测模块的调用,检验调用参数,并以尽可能简单的操作模拟被调用的子程序模块功能,把结果送回被测模块。顶层模块测试时不需要驱动模块,底层模块测试时不需要桩模块。

模块的内聚程度高可以简化单元测试过程。如果每个模块只完成一种功能,则需要的测试方案数目将明显减少,模块中的错误也更容易预测和发现。

3.集成测试

集成测试(Integration Testing),也称组装测试,它是对由各模块组装而成的程序进行测试,主要目标是发现模块间的接口和通信问题。例如,数据穿过接口可能丢失;一个模块对另一个模块可能由于疏忽而造成有害影响;把子功能组合起来可能不产生预期的主功能;个别看来是可以接受的误差可能积累到不能接受的程度;全程数据结构可能有问题等。集成测试主要发现设计阶段产生的错误,集成测试计划应该在概要设计阶段制定。

集成的方式可分为非渐增式和渐增式。

非渐增式集成是先测试所有的模块,然后一下子把所有这些模块集成到一起,并把庞大的程序作为一个整体来测试。这种测试方法的出发点是可以“一步到位”,但测试者面对众多的错误现象,往往难以分清哪些是“真正的”错误,哪些是由其他错误引起的“假性错误”,诊断定位和改正错误也十分困难。非渐增式集成只适合一些非常小的软件。

渐增式集成是将单元测试和集成测试合并到一起,它根据模块结构图,按某种次序选一个尚未测试的模块,把它同已经测试好的模块组合在一起进行测试,每次增加一个模块,直到所有模块被集成在程序中。这种测试方法比较容易定位和改正错误,目前在进行集成测试时已普遍采用渐增式集成。

渐增式集成又可分为自顶向下集成和自底向上集成。自顶向下集成先测试上层模块,再测试下层模块。由于测试下层模块时它的上层模块已测试过,所以不必另外编写驱动模块。自底向上集成先测试下层模块,再测试上层模块。同样,由于测试上层模块时它的下层模块已测试过,所以不必另外编写桩模块。这两种集成方法各有利弊,一种方法的优点恰好对应于另一种方法的缺点,实际测试时可根据软件特点及进度安排灵活选用最适当的方法,也可将两种方法混合使用。

4.确认测试

确认测试(Validation Testing)主要依据软件需求说明书检查软件的功能、性能及其他特征是否与用户的需求一致。确认测试计划应该在需求分析阶段制定。

软件配置复查是确认测试的另一项重要内容。复查的目的是保证软件配置的所有成分都已齐全,质量符合要求,文档与程序完全一致,具有完成软件维护所必需的细节。

如果一个软件是为某个客户定制的,最后还要由该客户来实施验收测试(Acceptance Testing),以便确认其所有需求是否都已得到满足。由于软件系统的复杂性,在实际工作中,验收测试可能会持续到用户实际使用该软件之后的相当长的一段时间。

如果一个软件是作为产品被许多客户使用的,不可能也没必要由每个客户进行验收测试。绝大多数软件开发商都使用被称为 α (Alpha)测试和 β (Beta)测试的过程,来发现那些看起来只有最终用户才能发现的错误。

α 测试由用户在开发者的场所进行,并且在开发者的指导下进行测试。开发者负责记录发现的错误和使用中遇到的问题。也就是说, α 测试是在“受控的”环境中进行的。

β 测试是在一个或多个用户的现场由该软件的最终用户实施的,开发者通常不在现场,用户负责记录发现的错误和使用中遇到的问题并把这些问题报告给开发者。也就是说, β 测试是在“非受控的”环境中进行的。

经过确认测试之后的软件通常就可以交付使用了。

5.白盒测试

白盒测试,又称结构测试,主要用于单元测试阶段。它的前提是把程序看成装在一个透明的白盒子里,测试者完全知道程序的结构和处理算法。这种方法按照程序内部逻辑设计测试用例,检测程序中的主要执行通路是否都能按预定要求正确工作。

白盒测试常用的技术是逻辑覆盖,即考查用测试数据运行被测程序时对程序逻辑的覆盖程度。主要的覆盖标准有六种:语句覆盖、判定覆盖、条件覆盖、判定/条件覆盖、组合条件覆盖和路径覆盖。

1)语句覆盖

语句覆盖是指选择足够多的测试用例,使得运行这些测试用例时,被测程序的每个语句至少执行一次。很显然,语句覆盖是一种很弱的覆盖标准。

2)判定覆盖

判定覆盖又称分支覆盖,它的含义是,不仅每个语句至少执行一次,而且每个判定的每种可能的结果(分支)都至少执行一次。

判定覆盖比语句覆盖强,但对程序逻辑的覆盖程度仍然不高。

3)条件覆盖

条件覆盖的含义是,不仅每个语句至少执行一次,而且使判定表达式中的每个条件都取到各种可能的结果。

条件覆盖不一定包含判定覆盖,判定覆盖也不一定包含条件覆盖。

4)判定/条件覆盖

同时满足判定覆盖和条件覆盖的逻辑覆盖称为判定/条件覆盖。它的含义是,选取足够的测试用例,使得判定表达式中每个条件的所有可能结果至少出现一次,而且每个判定本身的所有可能结果也至少出现一次。

5)条件组合覆盖

条件组合覆盖的含义是,选取足够的测试用例,使得每个判定表达式中条件结果的所有可能组合至少出现一次。

显然,满足条件组合覆盖的测试用例,也一定满足判定/条件覆盖。因此,条件组合覆盖是上述5种覆盖标准中最强的一种。然而,条件组合覆盖还不能保证程序中所有可能的路径都至少经过一次。

6)路径覆盖

路径覆盖的含义是,选取足够的测试用例,使得程序的每条可能执行到的路径都至少经过一次(如果程序中有环路,则要求每条环路径至少经过一次)。

路径覆盖实际上考虑了程序中各种判定结果的所有可能组合,因此是一种较强的覆盖标准。但路径覆盖并未考虑判定中的条件结果的组合,并不能代替条件覆盖和条件组合覆盖。

6.黑盒测试

黑盒测试,又称功能测试,主要用于集成测试和确认测试阶段。它把软件看做一个不透明的黑盒子,完全不考虑(或不了解)软件的内部结构和处理算法,它只检查软件功能是否能按照软件需求说明书的要求正常使用,软件是否能适当地接收输入数据并产生正确的输出信息,软件运行过程中能否保持外部信息(例如文件和数据库)的完整性等。

常用的黑盒测试技术包括等价类划分、边值分析、错误推测和因果图等。

1)等价类划分

在设计测试用例时,等价类划分是用得最多的一种黑盒测试方法。所谓等价类就是某个输入域的集合,对于一个等价类中的输入值来说,它们揭示程序中错误的作用是等效的。也就是说,如果等价类中的一个输入数据能检测出一个错误,那么等价类中的其他输入数据也能检测出同一个错误;反之,如果等价类中的一个输入数据不能检测出某个错误,那么等价类中的其他输入数据也不能检测出这一错误(除非这个等价类的某个子集还属于另一等价类)。

如果一个等价类内的数据是符合(软件需求说明书)要求的、合理的数据,则称这个等价类为有效等价类。有效等价类主要用来检验软件是否实现了软件需求说明书中规定的功能。

如果一个等价类内的数据是不符合(软件需求说明书)要求的、不合理或非法的数据,则称这个等价类为无效等价类。无效等价类主要用来检验软件的容错性。

黑盒测试中,利用等价类划分方法设计测试用例的步骤如下。

● 根据软件的功能说明,对每一个输入条件确定若干个有效等价类和若干个无效等价类,并为每个有效等价类和无效等价类编号。

● 设计一个测试用例,使其覆盖尽可能多的尚未被覆盖的有效等价类。重复这一步,直至所有的有效等价类均被覆盖。

● 设计一个测试用例,使其覆盖一个尚未被覆盖的无效等价类。重复这一步,直至所有的无效等价类均被覆盖。

应当特别注意,无效等价类用来测试非正常的输入数据,因此每个无效等价类都有可能查出软件中的错误,所以要为每个无效等价类设计一个测试用例。

2)边值分析

经验表明,软件在处理边界情况时最容易出错。设计一些测试用例,使软件恰好运行在边界附近,暴露出软件错误的可能性会更大一些。

通常,每一个等价类的边界,都应该着重测试,选取的测试数据应该恰好等于、稍小于或稍大于边界值。

将等价类划分法和边值分析法结合使用,更有可能发现软件中的错误。

3)错误推测

使用等价类划分和边值分析技术,有助于设计出具有代表性的、容易暴露软件错误的测试方案。但是,不同类型不同特征的软件通常又有一些特殊的容易出错的地方。错误推测法主要依靠测试人员的经验和直觉,从各种可能的测试方案中选出一些最可能引起程序出错的方案。

4)因果图

因果图法是根据输入条件与输出结果之间的因果关系来设计测试用例的,它首先检查输入条件的各种组合情况,并找出输出结果对输入条件的依赖关系,然后为每种输出条件的组合设计测试用例。

4.3.2 软件维护

软件维护就是在软件交付使用之后直至软件被淘汰的整个时期内为了改正错误或满足新的需求而修改软件的活动。

软件维护的代价是很大的,据1994年Software Engineering Encyclopedia记载,20世纪80年代末用于软件维护的花费约为整个软件生命周期总花费的75%,而且还在逐年上升。

1.软件维护类型

根据引起软件维护的原因,软件维护通常可分为以下四种类型:

1)改正性维护

改正性维护是指在使用过程中发现了隐蔽的错误后,为了诊断和改正这些隐蔽错误而修改软件的活动。

2)适应性维护

适应性维护是指为了适应变化了的环境而修改软件的活动。

3)完善性维护

完善性维护是指为了扩充或完善原有软件的功能或性能而修改软件的活动。

4)预防性维护

预防性维护是指为了提高软件的可维护性和可靠性、为未来的进一步改进打下基础而修改软件的活动。

2.软件的可维护性

软件的可维护性是指理解、改正、改动、改进软件的难易程度。根据Boehm质量模型,通常影响软件可维护性的因素有可理解性、可测试性和可修改性。

1)可理解性

可理解性是指维护人员理解软件的结构、接口、功能和内部过程的难易程度。

2)可测试性

可测试性是指测试和诊断软件错误的难易程度。

3)可修改性

可修改性是指修改软件的难易程度。

为了提高软件的可维护性,在软件生命周期的各个阶段都必须充分考虑维护问题。先进的软件工程方法是软件可维护的基础保证。

面向对象方法学的对象封闭机制、消息通信机制、继承机制和多态机制从根本上提高了软件的可理解性、可测试性和可修改性。

结构化设计的几条主要原则,如模块化、信息隐蔽、高内聚、低耦合等,对于提高软件的可理解性、可测试性和可修改性也都有重要的作用。

另外,书写详细正确的文档、书写源文件的内部注解、使用良好的编程语言、具有良好的程序设计风格,也有助于提高软件的可理解性。使用先进的测试工具、保存以前的测试过程和测试用例,则有助于提高软件的可测试性。

3.软件维护管理

软件维护管理是指为保证维护质量、提高维护效率、控制维护成本而进行的维护过程管理,它要求对软件的每次“修改”均需经过申请、评估、批准、实施、验证等步骤。

软件维护管理的核心是维护评估和维护验证。维护评估的主要工作包括:判定维护申请的合理性与轻重缓急、确定维护的可行性与时间及费用、制定维护策略与维护计划等。维护验证主要审查修改后的软件是否实现了维护目标、软件文档是否也做了相应修改等。 DTEbSzvqmC80B3bRvZW8RmtT2vmV9TlKaRkLcx3qQTQ5jtKQco+clTmqTqbVMxZG

点击中间区域
呼出菜单
上一章
目录
下一章
×