第十一章 测试评审方法
11.1 测试方法
“错误”主要针对软件开发过程,“缺陷”主要针对软件产品。软件测试的目的就是在软件投入生产性运行之前,尽可能多的发现软件产品(主要是指程序)中的错误(缺陷)。
为了发现软件中的错误(缺陷),应竭力设计能暴露错误(缺陷)的测试用例。测试用例是由测试数据和预期结果构成的。一个好的测试用例极有可能发现至今为止尚未发现的错误(缺陷)的测试用例。一次成功的测试是发现了至今尚未发现的错误(缺陷)的测试。
11.1.1 软件测试阶段
1. 单元测试
也称模块测试,通常可以放在编程阶段,由程序员对自己编写的模块自行测试,检查模块是否实现了详细设计说明书中规定的功能和算法。单元测试主要发现变成和详细设计中产生的错误,单元测试计划应该在详细设计阶段制定。
单元测试期间着重从以下几个方面对模块进行测试:模块接口、局部数据结构、重要的执行通路、出错处理通路和边界条件等。
测试一个模块时需要为该模块编写一个驱动模块和若干个桩模块。驱动模块用来调用被测模块,它接收测试者提供的测试数据,并把这些数据传送给被测模块,然后从被测模块中接收测试结果,并以某种可以看见的方式将测试结果返回给测试者。桩模块用来模拟被测模块所调用的子模块,它接收被测模块的调用,检验调用参数,并以尽可能简单的操作模拟被测模块所调用的子模块功能,把结果返回被测模块。顶层模块测试时不需要驱动模块,底层模块测试时不需要桩模块。
2. 集成测试
也称组装测试,它是对由各模块组装而成的程序进行测试,主要目标是发现模块间的接口和通信功能。集成测试主要发现设计阶段产生的错误,集成测试计划应该在概要设计阶段制定。
集成的方式可分为非渐增式和渐增式。
非渐增式集成是先测试所有的模块,然后一下子把所有这些模块集成到一起,并把庞大的程序作为一个整体来测试。只适合于一些非常小的软件。
渐增式集成是将单元测试和集成测试合并到一起,它根据模块结构图,按某种次序选一个尚未测试的模块,把它同已经测试好的模块组合在一起进行测试,每次增加一个模块,直到所有模块被集成在程序中。这种测试方法比较容易定位和改正错误。
渐增式集成又可以分为自顶向下集成和自底向上集成。自顶向下集成先测试上层模块,再测试下层模块。由于测试下层模块时它的上层模块已经测试过,所以不必另外编写驱动模块。自底向上集成先测试下层模块,再测试上层模块。同样,由于测试上层模块时他的下层模块已经测试过,所以不必另外编写桩模块。
3. 系统测试
是软件测试中最后的,最完整的测试,它是在单元测试和集成测试的基础上进行的,它从全局来考察软件系统的功能和性能要求。系统测试计划应该在需求分析阶段制定。
系统测试包括确认测试和验收测试。确认测试,主要依据软件需求说明书检查软件的功能、性能及其他葛铮是否与用户的需求一致。软件配置复查时确认测试的另一项重要内容。复查的目的是保证软件配置的所有成分都已齐全,质量符合要求,文档与程序完全一致,具有完成软件维护所必须的细节。
\alpha测试由用户在开发者的场所进行,并且在开发者的指导下进行测试。开发者负责记录发现的问题和使用中遇到的问题。也就是说,\alpha测试是在“受控的”环境中进行的。
\beta测试是在一个或多个用户的现场由该软件的最终用户实施的,开发者通常不在现场,用户负责记录发现的错误和使用中需要的问题并把这些问题报告给开发者。也就是说,\beta测试是在“不受控的”环境中进行的。
经过系统测试之后的软件通常就可以交付使用了。
11.1.2 白盒测试和黑盒测试
1. 白盒测试
又称结构测试,主要用于单元测试阶段。它的前提是可以把程序看成装在一个透明的白箱子里,测试者完全知道程序的结构和处理算法。这种方法按照程序内部逻辑设计测试用例,检测程序中的主要执行通路是否都能按预定要求正常工作。
白盒测试根据软件的内部逻辑设计测试用例,常用的技术是逻辑覆盖,即考察用测试数据运行被测程序对程序逻辑的覆盖程度。主要的覆盖标准如下:
- 语句覆盖。是指选择足够多的测试用例,使得运行这些测试用例时,被测程序的每个语句至少执行一次。是一种很弱的覆盖标准
- 判定覆盖。又称分支覆盖,含义是,不仅每个语句至少执行一次,而且每个判定的每种可能的结果都至少执行一次。比语句覆盖强,但对程序逻辑的覆盖程度仍然不高。
- 条件覆盖。含义是,不仅每个语句至少执行一次,而且使判定表达式中的每个条件都取得各种可能的结果。条件覆盖不一定包含判定覆盖,判定覆盖也不一定包含条件覆盖。
- 判定/条件覆盖。同时满足判定覆盖和条件覆盖的逻辑覆盖称为判定/条件覆盖。含义是,选取足够的测试用例,使得判定表达式中每个条件的所有可能结果至少出现一次,而且每个判定本身的所有可能结果也至少出现一次。
- 条件组合覆盖。含义是,选取足够的测试用例,使得每个判定表达式中条件结果的所有可能组合至少出现一次。满足条件组合覆盖的测试用例,也不一定更满足判定/条件覆盖。因此,条件组合覆盖是上述5种覆盖标准种最强的一种。然而,条件组合覆盖还不能保证程序中所有可能的路径都至少经过一次。
- 路径覆盖。含义是,选取足够的测试用例,使得程序的每条可能执行到的路径都至少经过一次(如果程序中有环路,则要求每条环路路径都至少经过一次)。路径覆盖实际上考虑了程序中各种判定结果的所有可能组合,因此是一种较强的覆盖标准。但路径覆盖并未考虑判定中的条件结果的组合,并不能代替条件符合和条件组合覆盖。
2. 黑盒测试
又称功能测试。主要用于集成测试和确认测试阶段,它把软件看做一个不透明的黑箱子,完全不考虑(或不了解)软件的内部结构和处理算法,只检查软件功能是否能按照软件需求说明书的要求正常使用,软件是否能适当的接收输入数据并产生正确的输出信息,软件运行过程中能否保持外部信息的完整性等。
黑河测试根据软件需求说明书所规定的功能来测试用例,不考虑软件的内部结构和处理算法。
常用的黑盒测试技术如下:
- 等价类划分。在设计测试用例时,等价类划分是用的最多的一种黑盒测试方法。就是某个输入域的集合,对于一个等价类的输入值来说,它们揭示程序中错误的输入是等效的。也就是说,如果等价类中的一个输入数据能检测出一个错误,那么等价类中的其他数据也能检测出同一个数据;反之,如果等价类中的一个输入数据不能检测出某个错误,那么等价类中的其他输入数据也不能检测出这一错误。
如果一个等价类中的数据是符合(软件需求说明书)要求的、合理的数据,则称这个等价类为有效等价类。有效等价类主要用来检验软件是否实现了软件需求说明书中规定的功能。
如果一个等价类内的数据是不符合(软件需求说明书)要求的、不合理或非法的数据,则称这个等价类为无效等价类。无效等价类主要用来检验软件的容错性。
黑盒测试中,利用等价类划分方法设计测试用例的步骤是:
- 根据软件的功能说明,对每一个输入条件确定若干个有效等价类和若干个无效等价类,并为每个有效等价类和无效等价类编号。
- 设计一个测试用例,使其覆盖尽可能多的尚未被覆盖的有效等价类,重复这一步,直至所有的有效等价类均被覆盖。
- 设计一个测试用例,使其覆盖一个尚未被覆盖的无效等价类。重复这一步,直至所有的无效等价类均被覆盖。
- 边值分析。经验表明,软件在处理边界情况时最容易出。设计一些测试用例,使软件恰好运行在边界附近,暴露出软件错误的可能性会大一些。
通常,每一个等价类的边界,都应该着重测试,选取的测试数据应该恰好等于、稍小于或稍大于边界值。 - 错误推测。使用等价类划分和边值分析技术,有助于设计出具有代表性的,容易暴露软件错误的测试方案。但是,不同类型不同特定的软件通常又有一些特殊的容易出错的地方。错误推测法主要依靠测试人员的经验和直觉,从各种可能的测试方案中选出一些最可能引起程序出错的方案。
- 因果图。是根据输入条件和输出条件之间的因果关系来设计测试用例的,它首先检查输入条件的各种组合情况,并找出输出结果对输入结果的依赖关系,然后为每种输出条件的组合设计测试用例。
11.1.3 缺陷的分类和级别
- 输入/输出错误。
- 逻辑错误
- 计算错误
- 接口错误
- 数据错误
错误的严重程度分类:
- 轻微:界面文字有个别的错别字,但不影响理解
- 中等:界面文字错误可能误导操作者
- 使人不悦:数字串被断开
- 影响使用:有些交易没有处理
- 严重:丢失交易
- 非常严重:不正确的交易处理
- 季度严重,经常出现不正确的交易
- 无法容忍:数据库遭到破坏
- 灾难性:系统无法工作
- 传染性:可导致其他系统无法工作
11.1.4 调试
又称为排错。测试成功的标志是发现了错误。根据错误迹象确定错误的原因和准确位置并加以改正,主要依靠排错技术。
隐藏在程序中的错误具有下列条数的性质:
- 错误的外部征兆远离引起错误的内部原因,对于高度耦合的程序结构此类现象更为严重。
- 纠正一个错误造成另一错误现象(暂时)的消失。
- 某些错误征兆只是假象。
- 因操作人员一时疏忽造成的某些错误征兆不易追踪
- 错误是由于分时而不是程序引起的
- 输入条件难以精确的再构造。
- 错误征兆时有时无,此现象对嵌入式系统尤其普遍。
- 错误是由于把任务分布在若干台不同处理机上运行而造成的。
常用的排错策略分为三类:
- 原始类。主要思想是“通过计算机找错”。
- 回溯类。方法是从出现错误征兆处开始,人工的沿控制流程往回追踪,直至发现出错的根源,不行的是程序变大后,可能的回溯路线显著增加,以致人工进行完全回溯可望而不可即。
- 排除类。基于归纳和演绎原理,采用“分治”的概念,首先分析与错误出现有关的所有数据,假想一个错误原因,用这些数据证明或反驳它,;或者一次列出所有可能的原因,通过测试一一排除。只要某次测试结果说明某种假设已呈现端倪,则立即精化数据,乘胜追击。
11.2 评审方法
- 软件需求评审。在软件需求分析结束后必须进行软件需求评审,以确保在软件需求说明书中所规定的各项需求的合适性。
- 概要设计评审。在软件概要设计结束后必须进行概要设计评审,以评价软件设计说明书中所描述的软件概要设计在总体结构、外部接主要部件功能分配、全局数据结构以及各主要部件之间的接口等方面的合适性。
- 详细设计评审。在软件详细设计结束后必须进行详细设计评审,以评价软件设计说明书中所描述的软件详细设计在每一个基本部件的工鞥呢、算法和过程描述等方面的合适性。
- 软件验证和确认评审。在软件验证与确认计划完成后必须进行软件验证与确认评审,以评价软件验证与确认计划中所规定的验证与确认方法的合适性和完整性。
- 功能检查。在软件释放前,要对软件进行功能检查,以验证所开发的软件已经满足在软件需求说明书中规定的所有需求。
- 物理检查。在软件验收前,要对软件进行物理检查,以验证程序和文档已经一致并做好了交付的准备。
- 综合检查。在软件验收时,要允许用户或用户所委托的软件对所要要收的软件进行设计抽样的综合检查,已验证代码和设计文档的一致性、接口规格说明的一致性(硬件和软件)、设计实现和功能需求的一致性、功能需求和测试描述的一致性。
- 管理评审。要对计划的执行情况定期(或按阶段)进行历评审,这些评审必须由独立于被评审单位的机构或授权的第三方主持进行。
在评审过程中,以下几点值得注意:
- 不应以测试代替评审。
- 评审人员应关注产品而不应评论开发人员。
- 评审人员应关注于实质性问题。
- 评审会议不应变为问题解决方案讨论会。
- 评审应被安排进项目计划。
- 评审参与者应了解整个评审过程。
- 评审人员事先应对评审材料充分了解。
- 应重视精神的组织工作。
11.3 验证与确认
1. 验收
- 合同验证。应根据下列准则验证合同:
- 供方具有满足需求的能力
- 需求是一致的并覆盖了用户的需要
- 为处理需求变更和升级问题规定了适当的规程。
- 规定了各方之间的接口及其合作规程与范围,包括所有权、许可权、版权和保密要求。
- 按照需求规定了验收准则和规程
- 过程验证。应根据下列准则验证过程:
- 项目是适当的、及时的。
- 为项目选择的过程是适当的并满足合同要求的。
- 用于项目过程的标准、规程和环境是适当的。
- 根据合同要求为项目配备了经过培训的人员。
- 需求验证。应根据下列准则验证需求:
- 需求是明确的、一致的、无歧义的
- 需求是可行的。
- 需求是可测试的。
- 设计验证。应根据下列准则验证设计:
- 设计师正确的,是可以实现需求的。
- 可以从需求导出设计,可以从设计追踪需求
- 编码验证。应根据下列准则验证编码:
- 编码是正确的,可以实现设计和需求。
- 可以从设计导出编码,可以从编码追踪设计
- 集成验证。应根据下列准则验证集成:
- 每一个软件项的软件部分和软件单元已完整、正确的集成到软件项中。
- 系统的硬件项、软件项和人工操作已完整、正确的集成到系统中。
- 文档验证。应根据下列准则验证文档:
- 文档是充分的,完备的、一致的。
- 文档制定是及时的。
- 文档配置管理遵循了规定的规程。
2. 确认
- 编写测试需求、测试用例和测试规程。
- 确保这些测试需求、测试用例和测试规程可以反映软件产品的预期用途。
- 执行测试
- 确认软件产品满足其预期用途。
11.4 测试自动化
一些适于考虑进行自动化的测试工作为:
- 测试用例的生成(包括测试输入、标准输出、测试操作指令等)
- 测试的执行控制(包括单机与网络多机分布运行、夜间及假日运行、测试用例调用控制、测试对象、范围、版本控制等)
- 测试结果与标准输出的对比
- 不吻合的测试结果的分析、记录、分类和通报
- 总测试状况的统计,报表的产生
11.5 面向对象的测试
1. 面向对象测试模型
面向对象的软件测试分为:面向对象分析的测试、面向对象设计的测试、面向对象编程的测试、面向对象的单元测试、面向对象的集成测试和面向对象的系统测试。
2. 面向对象分析的测试
传统的面向过程分析是一个功能分解的过程,是把一个系统看成可以分解的功能的集合。功能分解分析法的着眼点在于一个系统需要什么样的信息处理方法和过程,以过程的抽象来对待系统的需要。面向对象的分析直接映射问题空间,将问题空间内的实例抽象为对象,用对象的结构反映问题空间的复杂实例和复杂关系,用属性和操作表示实例的特性和行为。OOA的结果为后面阶段类的选定和实现、类层次结构的组织和实现提供平台。因此,对OOA的测试,应从以下方面考虑:
- 对认定的对象的测试。
- 对认定的结构的测试
- 对认定的主题的测试
- 对定义的属性和实例关联的测试
- 对定义的服务和消息关联的测试
3. 面向对象设计的测试
传统的结构化设计方法,采用面向作业的思路,它把系统分解以后,提出一组作业,这些作业是以过程实现系统的基础构造,把问题域的分析转化为求解域的设计,分析的结果是设计阶段的输入。而OOD以OOA为基础归纳出类,并建立类结果或进一步构造成类库,实现分析结果对问题空间的抽象。OOD确定类和类结构不仅满足当前需求分析的要求,更重要的是通过重新组合或加以适当的补充,能够方便的实现功能的重用和扩充,以不断适应用户的要求。因此,对OOD的测试,应从如下三个方面考虑:
- 对认定的类的测试
- 对构造的类层次结构的测试
- 对类库的支持的测试
4. 与面向对象编程的测试
在OOP阶段,忽略类功能实现的细则,将测试的焦点集中在类功能的实现和相应的面向对象程序风格,主要体现为以下两个方面:
- 数据成员是否满足数据封装的要求
- 类是否实现了要求的功能
5. 面向对象的单元测试
将操作作为类的一部分
6. 面向对象的集成测试
对OO软件的集成测试也有两种不同策略:第一种称为基于线程的测试,集成系统的一个输入或事件所需的一组类,每个线程被集成并分别测试,并使用回归测试以保证没有产生副作用。第二种称为基于使用的测试,首先测试那些几乎不使用其他类的类(称为独立类)并开始构造系统,当独立类测试完成后,下一层的使用独立类的类(称为依赖类)被测试。这个依赖类层次的测试序列以致持续到构造完整个系统。
7. 面向对象的系统测试
系统测试时,应该参考OOA分析的结果,对应描述的对象、属性和各种服务,检查软件是否能够完全”再现“问题空间。系统测试不仅是检查软件的整体行为表现,从另一个侧面看,也是对软件开发设计的再确认。