关闭

如何编写干净的单元测试用例

发表于:2008-6-11 16:43

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:未知    来源:51Testing软件测试论坛

        如你所见,我们在这里定义了setupEnv()和cleanEnv()两个方法,分别用于初始化环境和清除测试数据,然后在测试方法开始和结束时分别调用这两个方法。这的确达到了我们的目的,不用在每个测试方法中都编写初始化和清除逻辑!但此时你一定发现在每个测试方法前后都调用setupEnv()和cleanEnv()也很不爽,那说明我们的抽象程度还不够!那么该如何做的更好呢?

        这里该到模板方法(Template Method)模式发挥威力的时候了。我们将使用模板方法来继续重构前面的案例。让我们先来定义一个方法:

/**
* @author tao.youzt
*/
public class TestBizUrlDAO extends AbstractDependencyInjectionSpringContextTests {
private BizUrlDAO bizUrlDAO;
@Override
protected String[] getConfigLocations() {
return new String[]{"godzilla-dao.xml","godzilla-db.xml"};
}
protected void setupEnv(){
bizUrlDAO.delete("www.easyjf.com");
}
protected void cleanEnv(){
bizUrlDAO.delete("www.easyjf.com");
}
public void testTemp(){
//do test logic in this method
execute();
}
protected void execute(){
setupEnv();
doTestLogic();
setupEnv();
}
}
        相比之前的方法,我们这里已经有了一些进步,定义了一个execute方法,在该方法开始和结束分别执行初始化和清除逻辑,然后由doTestLogic()方法实现测试逻辑。实际测试方法中只要执行execute方法,并传入测试逻辑就可以了。瞧,不经意间我们已经实现了模板方法模式——把通用的逻辑封转起来,变化的部分由具体方法提供。怎么,不相信么?呵呵,设计模式其实并不复杂,就是前人解决通用问题的一些最佳实践总结而已。

        此时你可能会说,TeseCase类已经提供了setUp()和tearDown()方法来做这件事情,我也想到了,哈哈!但这并不和本文产生冲突!
    
        问题似乎越来越清晰,但我们遭遇了一条无法跨越的鸿沟——如何才能把测试逻辑传递到execute方法中呢?单靠传统的编程方法已经无法解决这个问题,因此我们必须寻找其他途径。

        可能此时此刻你已经想到,本文另一个重要概念——回调方法模式还没有用到,是不是该使用该模式了?没错,就是它了!我先把代码给出,然后再详细解释。

        我们提供了一个抽象类TestExecutor,并定义一个抽象的execute方法,然后为测试类的execute方法传入一个TestExecutor的实例,并调用该实例的execute方法。最后,我们的测试方法中只需要new一个TestExecutor,并在execute方法中实现测试逻辑,便可以按照预期的方式执行:准备测试环境-执行测试逻辑-清除测试数据。这便是一个典型的回调方法模式的应用!

        模板方法和回调函数模式说起来挺悬,其实也就这么简单,明白了吧:)

    三、如何为每个测试方法单独提供环境方法呢? 

        通过前面的讲解,相信大家对模板方法和回调函数模式都已经掌握了,这里直接给出相关代码:

/**
* DAL层测试支持类.
*
*
* 除非特殊情况,所有DAO都要继承此类.
*
* @author tao.youzt
*/
public abstract class GodzillaDalTestSupport extends AbstractDependencyInjectionSpringContextTests {
/*
* @see org.springframework.test.AbstractDependencyInjectionSpringContextTests#getConfigLocations()
*/
@Override
protected final String[] getConfigLocations() {
String[] configLocations = null;
String[] customConfigLocations = getCustomConfigLocations();
if (customConfigLocations != null && customConfigLocations.length > 0) {
configLocations = new String[customConfigLocations.length + 2];
configLocations[0] = "classpath:godzilla/dal/godzilla-db-test.xml";
configLocations[1] = "classpath:godzilla/dal/godzilla-dao.xml";
for (int i = 2; i < configLocations.length; i++) {
configLocations[i] = customConfigLocations[i - 2];
}
return configLocations;
} else {
return new String[] { "classpath:godzilla/dal/godzilla-db-test.xml",
"classpath:godzilla/dal/godzilla-dao.xml" };
}
}
/**
* 子类可以覆盖该方法加载个性化配置.
*
* @return
*/
protected String[] getCustomConfigLocations() {
return null;
}
/**
* 准备测试环境.
*/
protected void setupEnv() {
}
/**
* 清除测试数据.
*/
protected void cleanEvn() {
}
/**
* 测试用例执行器.
*/
protected abstract class TestExecutor {
/**
* 准备测试环境
*/
public void setupEnv() {
}
/**
* 执行测试用例.
*/
public abstract void execute();
/**
* 清除测试数据.
*/
public void cleanEnv() {
}
}
/**
* 执行一个测试用例.
*
* @param executor
*/
protected final void execute(final TestExecutor executor) {
execute(IgnoralType.NONE, executor);
}
/**

64/6<123456>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号