2008年11月3日星期一

在Junit测试中使用 “前提”

在Cruise团队,QA经常会提交这样的bug, "某某功能在Windows上不工作 ",当然我并没有歧视Windows的意思,Windows在这句话里可以被替换为OSX, LINUX,乌龟SVN, Collable SVN,等等。在这样的团队中,面临着更多的不同平台(不仅仅是操作系统,还有不同发行版)带来的挑战。即便是Java这样号称“一次编写,随处运行”的语言,也必须常常去处理不同平台之间的些许差异。

作为一个TDDer,我们修复上述的bug的步骤是:

* 找到一台Windows机器
* 对上述Bug编写测试
* 运行测试得到“Red bar”
* 修改产品代码
* 运行测试得到"Green bar"


但是这样一个好的测试,却很可能无法提交,因为这特定平台的补丁可能会让别的测试失败。

这时候的无奈之选就是

@Test
public void featureShouldWorkOnWindows {
if (OSUtil.isWindows()) {
//Run the test.
}
}


这样,我们修复了bug,也编写了可靠的测试,除了测试代码有一点ugly. 这样的代码多了 ,也终究是一件恼火的事情。

前几天,写了一个对Junit的扩展,对于上面的测试,
可以这样来写
@RunWith(PrerequisiteAwareClassRunner.class)
public class TestCasesOnDifferentOS {
@Test
@Prerequisite(checker = OSChecker.class, arguments = OSChecker.LINUX)
public void shouldPassOnLinuxPlatform() throws Exception {
}
}

在这里,引入了前提条件@Prerequisite, 只有当前提满足的时候才会运行测试。

在项目里一个真实的例子是我们使用了ab(apache出品的性能测试工具,可以通过命令行调用)来进行性能测试,但并非所有的平台都能方便的安装ab。并且这个测试也无需在所有的平台上运行,通过使用前提,可以写下测试:
@RunWith(PrerequisiteAwareClassRunner.class)
public class TestCasesOnDifferentOS {
@Test
@Prerequisite(checker = AppsInstalledChecker.class, arguments = "ab -V")
public void shouldRunPerfWhenABIsInstalled() throws Exception {
}
}

在这里AppsInstalledChecker通过运行“ab -V”,并利用返回值判断是否当前平台上安装了ab,从而相应的运行或者忽略测试。


@Prerequisite中的Checker是一个接口
package com.googlecode.junit.ext;

public interface Checker {
boolean satisfy();
}
任何人都可以通过继承这个接口在扩展出适合应用场景的Checker。

@Prerequisite不是用于解决产品代码中的平台问题,作为junit的扩展,可以使用它让测试代码更干净,可读。

如果有兴趣,可以访问 http://code.google.com/p/junit-ext/来尝试一下。

Feedback或者Feature Request请发到:

iamkaihu@gmail.com
zee.ho.81@gmail.com

1 条评论:

cynosure 说...

Annotation的功劳不小。