一个基于面向对象语言的白盒测试模式(以Java为例)
作者:廖光明 (liaogm2002@hotmail.com)
1 概要
1.1 目的
规范项目单元与集成测试过程,统一集成测试、单元测试架构和用例设计,达到测试用例维护性,复用性较好,路径覆盖高的目的。
1.2 术语说明
为便于沟通,引入如下术语表述:
1) Unit
对于过程性软件,指程序模块或组件;对于面向对象软件指Class,如果Class太大时,也可以操作/方法作为单元。
2) Unit Test
以Unit为范围,测试一个功能集中很详细具体的单个方面,也称为Logic Unit test。
对面向对象软件的单元测试,指对某个单独的类编写测试用例. 一般指对类的方法独立进行的测试,测试方法之间无依赖关系,而测试所依赖的外部环境依靠mock或者stubs来控制,logic unit tests 是白盒测试的基础,一般由开发此程序单元的人员负责完成。
3) Integration test
用于检查已通过Logic Unti test 的Class的集成协作操作是否符合需求设计说明,也称为Integration Unti test。
在面向对象程序设计中,Integration unit tests是白盒测试的关键。
4) Functional unit test
用于检查已经通过Integration Unti test的Class Package输入接口、输出接口是否与需求说明一致,以级检查Package内部可能的冗余代码。
当Integration test满足覆盖性要求(包括正常功能覆盖与异常处理覆盖)时,Functional Unit test测试方法类似于系统测试,不关注内部代码实现,其测试过程可参考本人后续的系统测试规范。
三种测试单元关系如下图:
2 适用范围
适用于面向对象编程的系统。
3 测试框架
使用Junit + Ant + CodeCoverage 作为测试框架。
4 单元测试基本规则
4.1 单元测试范围
4.1.1需要进行单元测试的类
除自动生成的Entity EJB外所有的Java类都需要实施单元测试,其中对Servlet、JSP暂缓实施。
4.1.2 需要进行单元测试的方法
原则:对其他对象可能会访问的所有方法需要进行显式的单元测试;
1) 对public和缺省访问权限的方法都需要进行显式的单元测试;
2) 对private、protected方法的单元测试已经隐含在(1)中,无需再进行单独的单元测试;
3) 对setter/getter方法无需进行单元测试,除非它们执行了set/get其属性以外的其他动作;
4.2 测试用例的设计
测试用例是针对方法的,亦即方法的实参用例。测试用例应该包括所有的可能输入情况。
所有单元集成测试都应该实现的测试用例:
1) 正常运行的测试用例;
2) 设计的应当出错(发生异常)的测试用例;
3) 参数为特殊值的测试用例;
4) 常见的各类参数的特殊值:
A. Object类型的参数值为null时;
B. String类型的参数值为””时;
C. 数字类型的参数置为0时;
D. 其他特殊情况;
4.3 测试的记录
应该在类设计文档中用统一的格式记录对该类的单元测试情况;
单元测试的说明结合在类说明文档中,对每一个类的说明文档,都要指明其单元测试类;对每一个被测试类的每一个需要进行单元测试的方法,都要指明其测试方法并说明测试用例;其格式如下:
| 测试用例(形参列表) | 预期结果 | 实际结果 | 是否通过 | 备注 |
|
|
|
|
|
|
|
|
|
|
|
|
对于复杂的测试用例可不受此格式限制,但必须包含此表格内容。
4.4 测试的实现
1. 测试类命名规则:在被测试类名前加Test,即TestClassName;
2. 对被测试类的每一个需要进单元测试的方法,在单元测试类中建立一个无参数的测试方法,形式如下:public void testMethodName();
3. 对被测试的方法的所有测试用例均放在testMethodName()中执行,无需对每一个测试用例建立一个测试方法;
4. 测试类的位置:与被测试类放在同一个package中,但物理存储位置在test目录下(被测的程序代码在src目录下);
5. 在setUp()中仅定义所有test方法都需要的初始化处理;在tearDown()方法中仅定义所有test方法都需要的结束处理;
6. 每个Package下包含一个名字为AllTests的类,实现public static Test suite()方法,返回以Package全路径命名的TestSuite对象,其中包含了该Package下所有的Test对象;
7. 可借助于Mock Object实现单元测试;
8. 可用JBuilder可以用向导生成单元测试类的框架。
5 Integration Unit Test规则
5.1 集成测试范围
由消息连接起来的方法执行序列所覆盖的Class集合,作为一个集成测试单元,常把消息输入Interface和输出Interface作为测试单元的边界。
基于UML表示方法的协作图显示了Class间消息的传输,既单元的调用关系,从而确定一个集成测试单元。
为上述协作图中,如果以testIt和Date作为集成测试单元,则为Year, Month,Day 建立桩(Stub),以形成testIt和Date集成测试单元的边界,从而形成一个完整的测试单元范围。
5.2 集成测试用例设计
在确定集成测试单元边界后,通过消息的开始/结束Interface的消息事件确定集成测试路径,对每条路径的不同状态都需要设计测试用例。
UML表示的序列图可作为确定路径的重要依据。
printDate消息序列图
上述序列图中,通过为Class: Day, Month, Year 建立Stubs,对集成测试单元进行隔离,则printDate()的起始输入Interface为testIt,结束输出Interface为Date,从而确定一条消息路径。
每条消息路径会由不同Class的状态组成,因此,每条消息路径对应多个测试用例。
5.3 集成测试记录
集成测试用例记录格式如下:
| 消息-事件 | case | 测试用例(形参列表) | 预期结果 | 实际结果 | 是否通过 | 备注 | |
| Begin_Interface | End_Interface |
|
|
|
| ||
| increment | Case1 | (p1,p2,…) | (pm,pn,…) |
|
|
|
|
| case2 | …… | …… |
|
|
|
| |
| create | case3 |
|
|
|
|
|
|
| case4 |
|
|
|
|
|
| |
| … |
|
|
|
|
|
| |
| PrintDate | case n |
|
|
|
|
|
|
对于复杂的测试用例经可不受此格式限制,但必须包含此表格内容。
5.4 测试实现
集成测试测试框架与单元测试框架一样,使用Junit。因此实现方式与单元测试相同
6 测试用例度量参数
1) 自动化(Automatic)
l 结合ant或maven,或则持续集成框架来搭建基础结构
l 测试用例应该尽可能的与外部环境资源隔离(数据库,网络连接, 文件系统…)
l 分离需要手工测试(任何需要人为介入)的测试用例
2) 全面彻底 (Thorough)
l 测试尽可能多的代码行,分支和异常
l 测试尽可能多的边界条件
l 使用代码覆盖率(Code coverage)工具来量化测试
3) 可重复运行 (Repeatable)
l 保持与环境的隔离(使用 Mock object 或 stub)
l 确保每次测试的结果都与上次相同
4) 独立的 (Independent)
l 每个测试之间保持独立
l 每个测试方法只对类的单个方法做测试
5) 快速的 (Fast)
l 尽可能少的依赖外部资源(很大程度上依赖于代码的具体实现)
l 分离毫时测试用例
6) 专业的 (Professional)
l 以编写产品代码的标准编写测试代码
l 以维护产品的标准维护测试用例
7 测试覆盖率检查
测试覆盖率,简单的说就是衡量测试活动覆盖产品代码的指标,测试覆盖率是衡量测试质量的一个重要参数。
常用测试覆盖率衡量指标有:
1) Line coverage
用于评测产品代码独立代码行在测试活动中执行的行覆盖率。此覆盖率指标往往忽略代码注释,Import语句,字段声明语句等。由于缺乏对逻辑分支的测试的统计,无法全面衡量代码的质量。
2) Basic block coverage
把非分支的代码区域做为一个计量单位.用于一个if/else中的某个分支行数远大于另 一个分支。所以可能会出现这项指标比较高的情况。
3) Method coverage
评测产品代码在测试活动中执行方法的覆盖率。
4) Class coverage
用于评测产品代码在测试活动中执行的类的覆盖率
5) Branch coverage
用于评价代码分支地测试覆盖率。
根据ANSI-178B的标准和IBM的经验,建议Line Coverage与Branch Coverage同时达到100%覆盖率。
在以unit + Ant + CodeCoverage测试框架中,需满足Line,Method, Block的100%覆盖。
作者
本文详细介绍了基于面向对象语言(以Java为例)的白盒测试模式,包括单元测试和集成测试的基本规则、用例设计、记录和实现。强调了测试的覆盖性和复用性,提出了测试框架、测试用例度量参数和测试覆盖率检查的重要性。
1091

被折叠的 条评论
为什么被折叠?



