第3章 软件测试过程

3.1  软件测试流程概述

  软件测试流程与软件开发流程类似,也包括测试计划、测试设计、测试开发、测试执行和测试评估几个部分。

  (1) 测试计划。根据用户需求报告中关于功能要求和性能指标的规格说明书,定义相应的测试需求报告,使得随后所有的测试工作都将围绕着测试需求来进行。同时,适当选择测试内容,合理安排测试人员、测试时间及测试资源等。

  (2) 测试设计。测试设计是指将测试计划阶段制订的测试需求分解、细化为若干个可执行的测试过程,并为每个测试过程选择适当的测试用例,保证测试结果的有效性。

  (3) 测试开发。建立可重复使用的自动测试过程。

  (4) 测试执行。执行测试开发阶段建立的自动测试过程,并对所发现的缺陷进行跟踪管理。测试执行一般由单元测试、集成测试、确认测试以及回归测试等步骤组成。

  (5) 测试评估。结合量化的测试覆盖域及缺陷跟踪报告,对应用软件的质量和开发团队的工作进度及工作效率进行综合评价。

  在上述测试流程中,测试执行按以下步骤进行:单元测试、集成测试、确认测试和验收测试,如图3.1所示。

图3.1  软件测试执行过程

  (1) 单元测试:通过对每个最小的软件模块进行测试,对源代码的每一个程序单元实行测试,检查各个程序模块是否正确地实现了规定的功能,确保其能正常工作。

  (2) 集成测试:对已测试过的模块进行组装集成,目的在于检验与软件设计相关的程序结构问题。

  (3) 确认测试:检验软件是否满足需求规格说明中的功能和性能需求,确定软件配置完全、正确。同时检验软件产品能否与实际运行环境中整个系统的其它部分(如硬件、数据库及操作人员)协调工作。

  (4) 验收测试:作为检验软件产品质量的最后一道工序,主要让用户对软件进行测试,并重新执行已经做过的测试的某个子集,保证没有引入新的错误。

3.2  单 元 测 试

  1.单元测试内容

  单元测试针对程序模块进行测试,主要有以下5个任务:模块接口测试、局部数据结构测试、边界条件测试、执行路径测试和出错处理测试,如图3.2所示。

图3.2  单元测试要解决的任务

  1) 模块接口测试

  通过对被测模块的数据流进行测试,检查进出模块的数据是否正确。因此,必须对模块接口,包括参数表、调用子模块的参数、全程数据、文件输入/输出等操作进行测试。具体涉及以下内容。

  (1) 模块接受输入的实际参数个数与模块的形式参数个数是否一致。

  (2) 输入的实际参数与模块的形式参数的类型是否匹配。

  (3) 输入的实际参数与模块的形式参数所使用的单位是否一致。

  (4) 调用其它模块时,所传送的实际参数个数与被调用模块的形式参数的个数是否相同。 

  (5) 调用其它模块时,所传送的实际参数与被调用模块的形式参数的类型是否匹配。

  (6) 调用其它模块时,所传送的实际参数与被调用模块的形式参数的单位是否一致。

  (7) 调用内部函数时,参数的个数、属性和次序是否正确。

  (8) 在模块有多个入口的情况下,是否引用与当前入口无关的参数。

  (9) 是否修改了只读型参数。

  (10) 全局变量是否在所有引用它们的模块中都有相同的定义。

   

  如果模块内包括外部I/O,还应该考虑下列因素:

  (1) 文件属性是否正确。

  (2)  OPEN与CLOSE语句是否正确。

  (3) 缓冲区容量与记录长度是否匹配。

  (4) 在进行读/写操作之前是否打开了文件。

  (5) 在结束文件处理时是否关闭了文件。

  (6) 正文书写/输入有无错误。

  (7)  I/O错误是否检查并做了处理。

   

  2) 局部数据结构测试

  测试用例检查局部数据结构的完整性,如数据类型说明、初始化、缺省值等方面的问题,并测试全局数据对模块的影响。

  在模块工作过程中,必须测试模块内部的数据能否保持完整性,包括内部数据的内容、形式及相互关系不发生错误。

  局部数据结构应注意以下几类错误:不正确的或不一致的类型说明;错误的初始化或默认值;错误的变量名,如拼写错误或书写错误;下溢、上溢或者地址错误。

   

  3) 执行路径测试

  测试用例对模块中重要的执行路径进行测试,其中对基本执行路径和循环进行测试往往可以发现大量路径错误。测试用例必须能够发现由于计算错误、不正确的判定或不正常的控制流而产生的错误。

  常见的错误如下:误解的或不正确的算术优先级;混合模式的运算错误;错误的初始化;精确度不够精确;表达式的不正确符号表示。

  针对判定和条件覆盖,测试用例能够发现如下错误:不同数据类型的比较错误;不正确的逻辑操作或优先级;应当相等的地方由于精确度的错误而不能相等;不正确的判定或不正确的变量;不正确的或不存在的循环终止;当遇到分支循环时不能退出;不适当地修改循环变量。

   

  4) 出错处理测试

  检查模块的错误处理功能是否包含错误或缺陷。例如,是否拒绝不合理的输入,出错的描述是否难以理解,是否对错误定位有误,是否出错原因报告有误,是否对错误条件的处理不正确,在对错误处理之前错误条件是否已经引起系统的干预等。

  测试出错处理的重点是当模块在工作中发生错误时,其中的出错处理设施是否有效。

   

  5) 边界条件测试

  边界条件测试是单元测试的最后一步,必须采用边界值分析方法来设计测试用例。测试在为限制数据处理而设置的边界处,测试模块是否能够正常工作。

  一些与边界有关的数据类型,如第一个、最后一个、最大值、最小值、最长、最短、最高、最低等。

  在边界条件测试中,应设计测试用例检查以下情况:

  (1) 在n次循环的第0次、1次……n次是否有错误。

  (2) 运算或判断中取最大值、最小值时是否有错误。

  (3) 数据流、控制流中刚好等于、大于、小于确定的比较值时是否出现错误。

   

  2. 单元测试步骤

  单元测试通常在编码阶段进行。在源程序代码编制完成并经过评审和验证,确认没有语法错误之后,开始设计单元测试的测试用例。

  模块并不是一个独立的程序,在考虑测试模块时,同时要考虑它和外界的联系,因此使用一些辅助模块去模拟与被测模块相关的其它模块。辅助模块分为以下两种:

  (1) 驱动模块(Drive):用来模拟被测模块的上一级模块,相当于被测模块的主程序,用于接收测试数据,并把这些数据传送给被测模块,启动被测模块,最后输出实测结果。

  (2) 桩模块(Stub):用来模拟被测模块工作过程中所调用的模块。桩模块一般只进行很少的数据处理,不需要把子模块的所有功能都带进来,但不允许什么事情也不做。

  被测模块、与它相关的驱动模块及桩模块共同构成了一个“测试环境”,如图3.3所示。

   

图3.3  单元测试的测试环境

   

3.3  集 成 测 试      

  按照软件设计要求,将经过单元测试的模块连接起来,组成所规定的软件系统的过程称为“集成”。集成测试就是针对这个过程,按模块之间的依赖接口关系图进行的测试。图3.4给出了软件分层结构的示例图。

  由于集成测试不是在真实环境下进行,而是在开发环境或是一个独立的测试环境下进行的,因此集成测试所需人员一般从开发组中选出,在开发组长的监督下进行。开发组长负责保证在合理的质量控制和监督下使用合适的测试技术执行充分的集成测试。在集成测试过程中,由一个独立测试观察员来监控测试工作。

   

图3.4  软件分层结构的示意图

   

  1. 集成测试的主要任务

  集成测试是组装软件的系统测试技术之一,按设计要求把通过单元测试的各个模块组装在一起之后,要求软件系统符合实际软件结构,发现与接口有关的各种错误。集成测试主要适应于如下几种软件系统:

  (1) 对软件质量要求较高的软件系统,如航天软件、电信软件、系统底层软件等。

  (2) 使用范围比较广、用户群数量较大的软件。

  (3) 使用类似C/C++带有指针的程序语言开发的软件。

  (4) 类库、中间件等产品。

   

  集成测试的主要任务是解决以下5个问题:

  (1) 将各模块连接起来,检查模块相互调用时数据经过接口是否丢失。

  (2) 将各个子功能组合起来,检查能否达到预期要求的各项功能。

  (3) 一个模块的功能是否会对另一个模块的功能产生不利的影响。

  (4) 全局数据结构是否有问题,会不会被异常修改。

  (5) 单个模块的误差积累起来是否被放大,从而达到不可接受的程度。

   

  2. 集成测试方法

  集成测试主要测试软件的结构问题,因此测试建立在模块接口上,多为黑盒测试,适当辅以白盒测试。执行集成测试应遵循如下步骤。

  步骤1:确认组成一个完整系统的模块之间的关系。

  步骤2:评审模块之间的交互和通信需求,确认模块间的接口。

  步骤3:生成一套测试用例。

  步骤4:采用增量式测试,依次将模块加入到系统并测试这个过程按逻辑/功能顺序重复进行。

   

  集成测试过程中尤其要注意关键模块测试,关键模块一般具有下述一个或多个特征:

  (1) 同时对应几项需求功能;

  (2) 具有高层控制功能;

  (3) 复杂,易出错;

  (4) 有特殊的性能要求。

  集成测试的主要目的是验证组成软件系统的各模块的接口和交互作用,因此集成测试对数据的要求从难度和内容上不是很高。集成测试一般不使用真实数据,可以使用一部分代表性的测试数据。在创建测试数据时,应保证数据充分测试软件系统的边界条件。

  集成测试包括非增量式集成测试和增量式集成测试。

   

  1) 非增量式集成测试方法

  非增量式集成测试方法采用一步到位的方法来进行测试,对所有模块进行个别的单元测试后,按程序结构图将各模块连接起来,把连接后的程序当作一个整体进行测试。

   

  2) 增量式集成测试方法

  增量式集成测试方法具体包括自顶向下增量式测试、自底向上增量式测试以及三明治集成测试。

  (1) 自顶向下增量式测试。自顶向下增量式测试按结构图自上而下进行逐步集成和逐步测试。模块集成的顺序是首先集成主控模块(主程序),然后按照软件控制层次结构向下进行集成。自顶向下的集成方式可以采用深度优先策略和广度优先策略,如图3.5所示。

   

图3.5  自顶向下增量式测试示意图

   

  (2) 自底向上增量式测试。自底向上增量式测试是从“原子”模块(软件结构中最底层的模块)开始,按结构图自下而上逐步进行集成和测试。图3.6表示采用自底向上增量式测试的过程。

   

图3.6  自底向上增量式测试示意图

   

  (3) 三明治集成测试。三明治集成也称混合集成,它将自顶向下和自底向上的优点和缺点集于一身。三明治集成是把系统分为三层,中间一层为目标层。测试时对目标层上面的一层采用自顶向下的集成测试方式,而对目标层下面的一层使用自底向上的集成策略,最后再对目标层进行测试。

  如图3.7所示,使用程序桩S2、S3和S4对用户界面M1进行测试,使用驱动程序D5和D6对最底层功能模块M7、M8和M9进行测试。当整个系统集成时,将程序桩S2、S3和S4换成中间层模块M2、M3和M4,驱动程序D5和D6对换成中间层模块M5和M6,从而对中间层的功能模块进行测试。

   

图3.7  三明治集成测试示意图

   

   

3.4  确 认 测 试

  确认测试用于验证软件的有效性,即验证软件的功能和性能及其它特性是否与用户的要求一致。

  在确认测试阶段需要做的工作如图3.8所示。首先要进行有效性测试以及软件配置复审,然后进行验收测试和安装测试,在通过了专家鉴定之后,才能成为可交付的软件。

   

图3.8  确认测试的步骤

   

  1. 有效性测试

  有效性测试是在模拟的环境下,运用黑盒测试的方法,验证被测软件是否满足需求规格说明书列出的需求。为此,需要制定测试计划,规定要做测试的种类,制定一组测试步骤,描述具体的测试用例。通过实施预定的测试计划和测试步骤,确定软件的特性是否与需求相符,确保所有的软件功能需求都能得到满足,所有的软件性能需求都能达到,所有的文档都是正确的且便于使用。

   

  2. 软件配置复查

  软件配置复查的目的是保证软件配置的所有成分,包括与实际运行环境中整个系统的支持环境都齐全,各方面的质量都符合要求。在确认测试的过程中,应当严格遵守用户手册和操作手册中规定的使用步骤,以便检查这些文档资料的完整性和正确性,记录发现的遗漏和错误,并且适当地补充和改正。

   

3.5  验 收 测 试

  验收测试是以用户为主的测试,软件开发人员和质量保证人员也应参加。由用户参加设计测试用例,通过用户界面输入测试数据,分析测试的输出结果。一般使用生产中的实际数据进行测试。在测试过程中,除了考虑软件的功能和性能外,还应对软件的可移植性、兼容性、可维护性、错误的恢复功能等进行确认。

   

3.5.1  α测试和β测试

  在软件交付使用之后,用户将如何实际使用程序,对于开发者来说是无法预测的。因为用户在使用过程中常常会发生各种问题,如对软件操作使用方法的误解;异常的数据组合;产生对某些用户来说似乎是清晰的,但对另一些用户来说却难以理解的输出,等等。

  α测试和β测试用于发现可能只有最终用户才能发现的错误。α测试可以是一个用户在开发环境下进行的测试,也可以是公司内部的用户在模拟实际操作环境下进行的测试。α测试是在受控制的环境下进行的测试。α测试的目的是评价软件产品的FURPS,即功能、可使用性、可靠性、性能和支持,尤其注重产品的界面和特色。α测试可以从软件产品编码结束之时开始,或在模块(子系统)测试完成之后开始,也可以在确认测试过程中产品达到一定的稳定度和可靠程度之后再开始。

   

  β测试是由软件的多个用户在一个或多个用户的实际使用环境下进行的测试。与α测试不同的是,开发者通常不在测试现场。因而,β测试是在开发者无法控制的环境下进行的软件现场应用。在β测试中,由用户记下遇到的所有问题,包括真实的以及主观认定的,定期向开发者报告;开发者在综合用户的报告之后,做出修改,最后将软件产品交付给全体用户使用。β测试着重于产品的支持性,包括文档、客户培训和支持产品生产能力。只有当α测试达到一定的可靠程度时,才能开始β测试。

   

3.5.2  回归测试

  软件生命周期中的任何一个阶段,只要软件发生了改变,就可能给该软件带来缺陷问题。而软件的改变可能是源于发现了错误并做了修改,也有可能是因为在集成或维护阶段加入了新的模块等多种情况。回归测试是一种验证已变更的系统的完整性与正确性的测试技术,是指重新执行已经做过的测试的某个子集,以保证修改没有引入新的错误或者发现由于更改而引起的之前未发现的错误,也就是保证改变没有带来非预期的副作用。因此,软件开发的各个阶段会进行多次回归测试。

   

  1.回归测试的实施前提

  (1) 当软件中所含错误被发现时,如果错误跟踪与管理系统不够完善,可能会遗漏对这些错误的修改;

  (2) 开发者对错误理解得不够透彻,也可能导致所做的修改只修正了错误的外在表现,而没有修复错误本身,从而造成修改失败;

  (3) 修改还有可能产生副作用从而导致软件未被修改的部分产生新的问题,使本来工作正常的功能产生错误。

   

  2.回归测试的两个策略

  回归测试是贯穿整个测试的各个阶段的测试活动,其目的是检验已经发现的缺陷有没有正确修改和修改过程中有没有引发新的缺陷。可以采用如下的策略进行回归测试。

  1) 完全重复测试

  完全重复测试是指将所有的测试用例全部再完全地执行一遍,以确认问题修改的正确性和修改后周边是否受到影响的测试方法。其缺点是由于要把用例全部执行,因此会增加项目成本,也会影响项目进度,所以很难完全执行。

   

  2) 选择性重复测试

  选择性重复测试是指可以选择一部分进行执行,以确认问题修改的正确性和修改后周边是否受到影响的测试方法。下面介绍几种选择性重复测试的方法:

  (1) 覆盖修改法。

  (2) 周边影响法。

  (3) 指标达成法。

  (4) 基于操作剖面测试法。

  (5) 基于风险选择测试法。

   

  3.回归测试的流程

  回归测试的流程一般具有如下步骤。

  步骤1:在测试策略制定阶段,制定回归测试策略。

  步骤2:确定回归测试版本。

  步骤3:回归测试版本发布,按照回归测试策略执行回归测试。

  步骤4:回归测试通过,关闭缺陷跟踪单。

  步骤5:回归测试不通过,缺陷单返回;开发人员重新修改,再次做回归测试。

   

  4.回归测试与一般测试的比较

  回归测试与一般测试相比具有许多不同点,下面分别从测试计划的可获性、测试范围、时间分配、开发信息、完成时间和执行效率等方面进行介绍。

  (1) 测试计划的可获性:一般测试根据系统规格说明书和测试计划,测试用例都是新的;而回归测试可能是更改了的规格说明书、修改过的程序和需要更新的测试计划。

  (2) 测试范围:一般测试的目标是检测整个程序的正确性;而回归测试的目标是检测被修改的相关部分的正确性以及它与系统原有功能的整合。

   

  (3) 时间分配:一般测试所需时间通常是在软件开发之前预算;而回归测试所需的时间(尤其是修正性的回归测试)往往不包含在整个产品进度表中。

  (4) 开发信息:一般测试关于开发的知识和信息可随时获取;而回归测试可能会在不同的地点和时间进行,需要保留开发信息以保证回归测试的正确。

  (5) 完成时间:由于回归测试只需测试程序的一部分,因此完成测试所需时间通常比一般测试所需时间少。

  (6) 执行频率:回归测试在一个系统的生命周期内往往要多次进行,一旦系统经过修改就需要进行回归测试。

发布了40 篇原创文章 · 获赞 2 · 访问量 5141

猜你喜欢

转载自blog.csdn.net/Dnesity/article/details/104807012