现在的位置: 首页 > 综合 > 正文

使用模拟对象(Mock Object)技术进行测试驱动开发

2013年04月16日 ⁄ 综合 ⁄ 共 2967字 ⁄ 字号 评论关闭

测试驱动开发是敏捷开发中重要部分。在现实项目中,开发人员通常希望减少对其它模块的依赖,把测试的单元与系统其它单元隔离。本文介绍敏捷开发并探讨测试驱动开发的重要性。对
mock 技术进行理论分析,并结合当前流行的 mock 软件如 jMock 和 EasyMock 等,展示测试驱动开发实例并进行比较。

敏捷开发

敏捷软件开发又称敏捷开发,是一种从上世纪 90
年代开始引起开发人员注意的新型软件开发方法。和传统瀑布式开发方法对比,敏捷开发强调的是在几周或者几个月很短的时间周期,完成相对较小功能,并交付使用。在项目周期内不断改善和增强。

2001 年初,在美国犹他州雪鸟滑雪胜地,17
名编程大师分别代表极限编程、Scrum、特征驱动开发、动态系统开发方法、自适应软件开发、水晶方法、实用编程等开发流派,发表“敏捷软件开发”宣言。其内容主要包括:

  • 人和交互重于过程和工具;
  • 可以工作的软件重于求全责备的文档;
  • 客户协作重于合同谈判;
  • 随时应对变化重于循规蹈矩;

可见在敏捷软件开发中,交付高质量的软件是非常重要的。只有交付可以工作的软件,开发人员才能不断地完成更多功能,而不是将大部分时间投入在修复软件产品缺陷
(Bug) 。所以如何提高交付软件的质量,在敏捷开发实施过程非常重要。



回页首

测试驱动开发

测试驱动开发,它是敏捷开发的最重要的部分。方法主要是先根据客户的需求编写测试程序,然后再编码使其通过测试。在敏捷开发实施中,开发人员主要从两个方面去理解测试驱动开发。

  • 在测试的辅助下,快速实现客户需求的功能。通过编写测试用例,对客户需求的功能进行分解,并进行系统设计。我们发现从使用角度对代码的设计通常更符合后期开发的需求。可测试的要求,对代码的内聚性的提高和复用都非常有益。

  • 在测试的保护下,不断重构代码,提高代码的重用性,从而提高软件产品的质量。可见测试驱动开发实施的好坏确实极大的影响软件产品的质量,贯穿了软件开发的始终。

在测试驱动开发中,为了保证测试的稳定性,被测代码接口的稳定性是非常重要的。否则,变化的成本就会急剧的上升。所以,自动化测试将会要求您的设计依赖于接口,而不是具体的类。进而推动设计人员重视接口的设计,体现系统的可扩展性和抗变性。



回页首

利用伪对象 (Mock
Obect) 实现接口测试

在实施测试驱动开发过程中,我们可能会发现需要和系统内的某个模块或系统外某个实体交互,而这些模块或实体在您做单元测试的时候可能并不存在,比如您遇到了数据库,遇到了驱动程序等。这时开发人员就需要使用
MO 技术来完成单元测试。

最开始,Mock Object 是完全由测试者自己手工撰写的。在这里我们可以举个简单的例子。

我们有一个移动数字电视卡的接口程序。

清单 1. VideoCardInterface
代码

				
public interface VideoCardInterface {

public void open();

public void changeChannel(int i);

public void close();

public Byte[] read();

public boolean fault();
}

下面是每个方法的功能说明:

  • open 打开移动数字电视卡。
  • changeChannel 切换移动数字电视频道。必须在打开之后才可以正常工作,否则就提示错误信息。
  • close 关闭移动移动电视卡。必须在打开之后才可以正常工作,否则就提示错误信息。
  • read 读取字节流。必须在打开之后才可以正常工作,否则就提示错误信息。
  • fault 显示当前工作状态。

由于相对应的硬件开发工作还没有完成,我们无法基于这样的接口程序进行实际的测试。所以开发人员基于接口,实现了部分移动电视卡的逻辑。

清单 2. MockVCHandler 代码

				
public class MockVCHandler implements VideoCardInterface {

private boolean initialized = false;
private boolean error = false;
private int channel;
private static final int DEFAULTCHANNEL = 1;

public void open() {
initialized = true;
channel = DEFAULTCHANNEL;
}

public void changeChannel(int i) {
if (!initialized) {
Assert.fail("Trying to change channel before open");
}
if (i <= 0) {
Assert.fail("Specified channale is out-of-range");
}
this.channel = i;
}

public void close() {
if (!initialized) {
Assert.fail("Trying to close before open");
}
}

public Byte[] read() {
if (!initialized) {
Assert.fail("Trying to read before open");
return null;
}
if (channel > 256) {
error = true;
Assert.fail("Channel is out-of-range");
}
return new Byte[] { '0', '1' };
}

public boolean fault() {
return error;
}
}

通过以上的实现,我们可以测试每个动作之间的先后逻辑关系,同时可以测试数据流读取出错的逻辑。如果测试人员进一步对数据流进行测试。还可以自我生成一段二进制字节流并进行测试。通过以上的实现,我们可以大大加快开发进度。在传统开发流程中,软件开发和测试不得不等大部分硬件都已经可以使用的条件下才可以开发测试。使用
MO 技术,使得硬件和软件在一定程度上可以同步开发和测试。

但是测试人员完全依靠自己实现这些类,不可避免的会带来测试用例编写效率低下和测试用例编写困难的弊病,甚至可能会影响 XP
实践者“测试先行”的激情。此时,各种各样帮助创建 Mock Object 的工具就应运而生了。目前,在 Java 阵营中主要的 Mock 测试工具有
jMock,MockCreator,MockRunner,EasyMock,MockMaker 等,在微软的 .Net 阵营中主要是
NMock,.NetMock,Rhino Mocks 和 Moq 等。



回页首

jMock 框架介绍

总体上来说,jMock 是一个轻量级的模拟对象技术的实现。它具有以下特点:

  • 可以用简单易行的方法定义模拟对象,无需破坏本来的代码结构表;
  • 可以定义对象之间的交互,从而增强测试的稳定性;
  • 可以集成到测试框架;
  • 易扩充;

与大多数 MOCK 框架一样,我们可以在 IDE 中使用并进行开发。本文以最常用的 Eclipse 为例。

下载 jMock

在 jMock 官方网站,我们可以下载当前稳定版本 jMock2.5.1 。

配置类路径

为了使用 jMock 2.5.1,您需要加入下面的 JAR 文件到当前的类路径。

  • jmock-2.5.1.jar
  • hamcrest-core-1.1.jar
  • hamcrest-library-1.1.jar

图 1. 已添加到
TestingExample 项目中 jMock 的 JAR 文件

本文转自IBM Developerworks中国

      请点击此处查看全文

 
 

抱歉!评论已关闭.