针对不同研发阶段的测试目的,测试活动分为需求测试、组件/单元测试、集成测试、系统测试、验收测试、Alpha测试、Beta测试、UAT测试等级别。

一、需求测试

软件测试双V模型要求测试工程师在需求阶段就开始制定系统测试计划,考虑系统测试方法,但这还不够。全面的质量管理要求在每个阶段都要进行验证和确认的活动。因此在需求阶段,测试工程师还需对需求本身进行测试。这个测试是必要的,因为在许多失败的项目中,70%~85%的返工是由于需求方面的错误所导致。因需求错误导致大量返工,造成进度延迟,缺陷发散甚至项目失败,这是一件极其痛苦的事情。因此测试工程师需在软件生产源头-需求就开始测试。

需求测试(Requirement Test)的重点是检查需求规格说明书中是否存在描述不准确、定义模糊、需求用例不正确、语言存在二义性等问题。主要从以下几个方面考虑。

1. 完整性。

每一项需求都必须将所要实现的功能描述清楚,为开发人员设计和实现这些功能提供所有必要的需求依据。

2. 正确性。

每一项需求都必须准确地陈述其要开发的功能。

3. 一致性。

一致性是指与其他软件需求或高层(系统、业务)需求不相矛盾,或者与项目宣传资料一致。

4. 可行性。

每一项需求都必须是在已知系统和环境的权能和限制范围内可以实施的。

5. 无二义性。

对所有需求说明书的读者都只能有一个明确统一的解释,由于自然语言极易导致二义性,所以尽量把每项需求用简洁明了的用户语言表达出来。

6. 健壮性。

需求说明中是否对可能出现的异常进行了分析,并且对这些异常进行了容错处理。

7. 必要性。

必要性可理解为每项需求都是用来授权编写文档的“根源”。要使每项需求都能回溯至某项客户的输入,如需求用例或其他来源。

8. 可测试性。

每项需求都能通过设计测试用例或其他的验证方法来进行测试。

9. 可修改性。

每项需求只应在软件需求规格说明书中出现一次。这样更改时易于保持一致性。另外,使用目录表、索引和相互参照列表方法将使软件需求规格说明书更容易修改。

二、 组件/单元测试

软件系统中,系统对象的基本组成单元称为组件或程序单元。程序代码中的函数或者类称为“单元”,或者实现某个独立需求的功能模块,称为组件/单元。组件可能由多个单元组成。

组件/单元测试(Unit Test)是针对软件基本组成单元(软件设计的最小单位)来进行正确性检验的测试工作,其目的是检测被测组件/单元与详细设计说明书的符合程度。通过组件/单元测试活动验证被测对象的功能特性或非功能性特性,发现其可能存在的内存泄露、算法冗余、分支覆盖率低、循环调用效率低等问题,此类缺陷在系统测试层面很难发现。因此,组件/单元测试能够尽早地发现缺陷,修复缺陷成本相对较低。

组件/单元测试一般由开发人员负责,成本较高。在敏捷研发模型中,测试工程师也可能需要实施此测试活动。组件/单元测试活动亦可以使用自动化测试方法。

组件/单元测试活动依据包括组件/单元需求说明、详细设计文档、被测代码、编程规范等,典型的测试对象一般有组件、函数、类、数据转换/移植程序、数据库模型、关键字典等,关注被测对象内部数据结构、逻辑控制、异常处理等实现的正确性。

【案例1 计算器单元测试】

一个计算器软件具有加、减、乘、除4种基本功能,对其实现单元测试,利用Junit单元测试工具实施如下。

计算器功能代码:

package com.test.junit3;

public class Calculator {

public static void main(String[] agrs)

{

}

public int add(int a,int b)

{

return a + b;

}

public int minus(int a,int b)

{

return a - b;

}

public int multi(int a,int b)

{

return a * b;

}

public int divd(int a,int b) throws Exception

{

if(b==0)

{

throw new Exception("除数不能为0!");

}

return a - b;//为了演示效果,此处构造错误的除法算法

}

}

单元测试代码:

package com.test.junit3;

import junit.framework.Assert;

import junit.framework.TestCase;

publicclass CalculatorTest extends TestCase{

publicvoid testAdd()

{

Calculator cal=newCalculator();

int result=cal.add(1, 2);

Assert.assertEquals(3, result);

}

publicvoid testMinus()

{

Calculator cal=newCalculator();

int result=cal.minus(1, 2);

Assert.assertEquals(-1, result);

}

publicvoidtestMulti()

{

Calculator cal=newCalculator();

int result=cal.multi(1, 2);

Assert.assertEquals(2, result);

}

publicvoid testDivd() throws Exception

{

Calculator cal=newCalculator();

int result=cal.divd(4, 1);

Assert.assertEquals(4, result);

}

}

测试结果图1所示。

图1——单元测试示例

从上述案例可以看出,除法功能测试失败,期望结果是4,但实际结果为3,查看代码,原因是除法功能代码错误,“a/b”错误写成“a-b”。执行单元测试时,仅关注每个函数或类单元的输入输出,根据预期结果与实际结果的对比,判断被测对象的正确与否。

三、集成测试

组件/单元测试通过后的组件或单元,即可进行集成测试。集成测试(Integration Testing)是对组件/单元之间及组件/单元与第三方接口之间进行测试,其目的是验证接口是否与设计相符,是否与需求相符。

集成测试根据被测对象的集成程度,可分为3种集成:组件/单元间集成、模块间集成、子系统间集成。集成的规模越大,发现定位缺陷的难度就越大,所以一般根据被测对象的系统结构特性,先从组件/单元间的集成测试开始,使用自底向上或自顶向下渐增式策略实施集成测试活动,大爆炸式集成策略已渐渐被淘汰。

【案例2计算器集成测试】

案例1单元测试中的计算器功能,假设加、减、乘、除4个功能为独立的类文件,使用集成测试自顶向上策略时,首先对各个类进行测试,然后测试主控模块,当除法代码如下时:

publicint divd(int a,int b) throws Exception

{

return a / b;

}

在实施集成测试,构造测试输入a=4,b=0时,将会抛出异常,如图2所示。

图2——集成测试异常示例

集成测试的目的是检测软件模块对《概要设计说明书》的符合程度,关注于模块间接口和接口数据传递关系,以及模块组合后的整体功能。集成测试实施人员一般是开发人员,当然也可以是测试工程师,现在不少企业集成测试实现了自动化测试,更聚焦于接口测试。

四、 系统测试

系统测试(System Test)是将通过集成测试的软件,部署到某种较为复杂的计算机用户环境进行测试,这里所说的复杂计算机用户环境,其实就是模拟的用户真实计算机环境。

集成测试阶段大多数情况下,是在一种比较干净的系统中进行测试。所谓的干净,即是在测试机上没有多余的软件,仅有所需的操作系统和被测软件。集成测试完成后,将被测软件置入比较复杂的运行环境下,进行集成和确认测试。在此过程中,往往有很大的收获,例如,进行安装测试时,会发现在集成阶段安装没有问题,但在复杂用户环境下,却不能安装。例如,某公司研发一款财务软件,软件中采用Excel 2000版中的某些绘图控件,在集成测试阶段,测试环境中仅安装了该财务软件和Excel 2000,但系统测试过程中,测试环境可能还安装了其他也需调用Excel控件的软件,这时可能会出现控件资源争用错误。

系统测试的目的在于通过与系统的需求定义做比较,发现软件与系统的需求定义不符合或与之矛盾的地方。系统测试阶段主要进行安装卸载测试、兼容性测试、功能确认测试、性能测试、安全性测试等。系统测试阶段采用黑盒测试方法,主要考查被测软件的功能与性能表现。如果软件可以按照用户合理的期望方式工作,即可认为通过系统测试,相反则表现为缺陷。图3所示是系统测试阶段发现的修改资产类别时,备注信息无法正确读取的缺陷,未能实现用户期望。

图3——系统测试备注读取错误缺陷示例

系统测试过程其实也是一种配置检查过程,检查在软件生产过程中是否有遗漏的地方,做到查漏补缺,以确保交付产品符合用户质量要求。

系统测试通常由独立的测试团队完成,其测试依据一般包括需求规格说明书、需求用例、功能规格说明、功能需求列表、风险分析报告等,以需求规格说明书为主。测试对象包括软件系统、用户手册、操作使用说明书、系统配置和配置数据等。

五、 验收测试

系统测试完成,在交付用户部署应用前,往往需要进行验收测试。验收测试(Acceptance Test)是以用户为主的测试,验收组应当由项目组成员、用户代表或系统的其他利益相关者等组成,原则上在用户所在地进行,但如经用户同意,也可以在公司内模拟用户环境进行。

验收测试根据合同、《需求规格说明书》或《验收测试计划》对成品进行验收测试。在此阶段,发现缺陷并不是其主要目的,期望通过验收测试,使用户建立对即将交付应用的软件系统的信心。

对于项目类的软件系统,一般都需要进行验收测试。验收测试通常情况下可有Alpha测试、Beta测试、UAT测试等验收测试形式。

六、 Alpha测试

Alpha测试是由用户在开发环境下进行的测试,也可以是在开发机构内部的用户模拟实际操作环境中进行测试。进行Alpha测试时,软件在一个自然设置状态下使用。开发者坐在用户旁,随时记下错误情况和使用问题,Alpha测试在受控的测试环境下实施,其目的主要是评价软件产品的FLURPS(即功能、局域化、可用性、可靠性、性能和技术支持)是否达标。

七、 Beta测试

Beta测试是由软件的多个用户在一个或多个用户的实际使用环境下进行的测试。与Alpha测试不同的是,进行Beta测试时,开发者通常不在测试现场。因而,Beta测试是在开发者无法控制的环境下进行的软件现场应用,测试者发现问题后,统一收集提交至开发人员进行修复。

八、UAT测试

UAT测试(User Acceptance Test)即用户接受度测试。一般用于商业用户验证系统的可用性。通常情况下,由采购方组织终端用户或软件利益相关方对被测对象进行选择性功能试用,关注被测对象核心功能的应用表现,从而为接受该软件系统提供数据依据。例如,银行在外包项目交付时,组织部分行方终端应用人员(如柜台服务人员)进行验收性测试,即为UAT测试。

UAT模式测试还有一种可能,就是根据法律法规、行业现行标准进行验收测试。例如,某政府机关采购的环保监控系统,需遵守政府管理需求及环保法规的约定。