您的位置:软件测试 > 开源软件测试 > 开源单元测试工具 > junit
单元测试利器JUnit
作者:网络转载 发布时间:[ 2013/3/29 14:59:08 ] 推荐标签:

    可是,这种 Fixture 设置方式还是引来了批评,因为它效率低下,特别是在设置 Fixture 非常耗时的情况下(例如设置数据库链接)。而且对于不会发生变化的测试环境或者测试数据来说,是不会影响到测试方法的执行结果的,也没有必要针对每一个测试方法重新设置一次 Fixture。因此在 JUnit 4 中引入了类级别的 Fixture 设置方法,编写规范如下:

    使用注解 org,junit.BeforeClass 修饰用于初始化 Fixture 的方法。
    使用注解 org.junit.AfterClass 修饰用于注销 Fixture 的方法。
    保证这两种方法都使用 public static void 修饰,而且不能带有任何参数。
类级别的 Fixture 仅会在测试类中所有测试方法执行之前执行初始化,并在全部测试方法测试完毕之后执行注销方法(图6)。代码范本如下:

引用
//类级别Fixture初始化方法
@BeforeClass public static void dbInit(){……}

//类级别Fixture注销方法
@AfterClass public static void dbClose(){……}

图6 类级别 Fixture 执行示意图

  异常以及时间测试

    注解 org.junit.Test 中有两个非常有用的参数:expected 和 timeout。参数 expected 代表测试方法期望抛出指定的异常,如果运行测试并没有抛出这个异常,则 JUnit 会认为这个测试没有通过。这为验证被测试方法在错误的情况下是否会抛出预定的异常提供了便利。举例来说,方法 supportDBChecker 用于检查用户使用的数据库版本是否在系统的支持的范围之内,如果用户使用了不被支持的数据库版本,则会抛出运行时异常 UnsupportedDBVersionException。测试方法 supportDBChecker 在数据库版本不支持时是否会抛出指定异常的单元测试方法大体如下:

Java代码 复制代码

    @Test(expected=UnsupportedDBVersionException.class)  
        public void unsupportedDBCheck(){  
            ……  
    } 

    注解 org.junit.Test 的另一个参数 timeout,指定被测试方法被允许运行的长时间应该是多少,如果测试方法运行时间超过了指定的毫秒数,则JUnit认为测试失败。这个参数对于性能测试有一定的帮助。例如,如果解析一份自定义的 XML 文档花费了多于 1 秒的时间,需要重新考虑 XML 结构的设计,那单元测试方法可以这样来写:

Java代码 复制代码

    @Test(timeout=1000)  
        public void selfXMLReader(){  
            ……  
    } 

  忽略测试方法

    JUnit 提供注解 org.junit.Ignore 用于暂时忽略某个测试方法,因为有时候由于测试环境受限,并不能保证每一个测试方法都能正确运行。例如下面的代码便表示由于没有了数据库链接,提示 JUnit 忽略测试方法 unsupportedDBCheck:

Java代码 复制代码

    @ Ignore(“db is down”)  
    @Test(expected=UnsupportedDBVersionException.class)  
        public void unsupportedDBCheck(){  
            ……  
    } 

    但是一定要小心。注解 org.junit.Ignore 只能用于暂时的忽略测试,如果需要永远忽略这些测试,一定要确认被测试代码不再需要这些测试方法,以免忽略必要的测试点。

测试运行器

    又一个新概念出现了——测试运行器,JUnit 中所有的测试方法都是由它负责执行的。JUnit 为单元测试提供了默认的测试运行器,但 JUnit 并没有限制您必须使用默认的运行器。相反,您不仅可以定制自己的运行器(所有的运行器都继承自 org.junit.runner.Runner),而且还可以为每一个测试类指定使用某个具体的运行器。指定方法也很简单,使用注解 org.junit.runner.RunWith 在测试类上显式的声明要使用的运行器即可:

Java代码 复制代码

    @RunWith(CustomTestRunner.class)  
    public class TestWordDealUtil {  
    ……  
    } 

  显而易见,如果测试类没有显式的声明使用哪一个测试运行器,JUnit 会启动默认的测试运行器执行测试类(比如上面提及的单元测试代码)。一般情况下,默认测试运行器可以应对绝大多数的单元测试要求;当使用 JUnit 提供的一些高级特性(例如即将介绍的两个特性)或者针对特殊需求定制 JUnit 测试方式时,显式的声明测试运行器必不可少了。

测试套件

  在实际项目中,随着项目进度的开展,单元测试类会越来越多,可是直到现在我们还只会一个一个的单独运行测试类,这在实际项目实践中肯定是不可行的。为了解决这个问题,JUnit 提供了一种批量运行测试类的方法,叫做测试套件。这样,每次需要验证系统功能正确性时,只执行一个或几个测试套件便可以了。测试套件的写法非常简单,您只需要遵循以下规则:

创建一个空类作为测试套件的入口。
    使用注解 org.junit.runner.RunWith 和org.junit.runners.Suite.SuiteClasses 修饰这个空类。
将 org.junit.runners.Suite 作为参数传入注解 RunWith,以提示 JUnit 为此类使用套件运行器执行。
    将需要放入此测试套件的测试类组成数组作为注解 SuiteClasses 的参数。
    保证这个空类使用 public 修饰,而且存在公开的不带有任何参数的构造函数。
Java代码 复制代码

    package com.ai92.cooljunit;  
     
    import org.junit.runner.RunWith;  
    import org.junit.runners.Suite;  
    ……  
     
    /** 
     * 批量测试 工具包 中测试类 
     * @author Ai92 
     */ 
    @RunWith(Suite.class)  
    @Suite.SuiteClasses({TestWordDealUtil.class})  
    public class RunAllUtilTestsSuite {  
    } 

    上例代码中,我们将前文提到的测试类 TestWordDealUtil 放入了测试套件 RunAllUtilTestsSuite 中,在 Eclipse 中运行测试套件,可以看到测试类 TestWordDealUtil 被调用执行了。测试套件中不仅可以包含基本的测试类,而且可以包含其它的测试套件,这样可以很方便的分层管理不同模块的单元测试代码。但是,您一定要保证测试套件之间没有循环包含关系,否则无尽的循环会出现在您的面前……。

参数化测试

    回顾一下我们在小节“JUnit 初体验”中举的实例。为了保证单元测试的严谨性,我们模拟了不同类型的字符串来测试方法的处理能力,为此我们编写大量的单元测试方法。可是这些测试方法都是大同小异:代码结构都是相同的,不同的仅仅是测试数据和期望值。有没有更好的方法将测试方法中相同的代码结构提取出来,提高代码的重用度,减少复制粘贴代码的烦恼?在以前的 JUnit 版本上,并没有好的解决方法,而现在您可以使用 JUnit 提供的参数化测试方式应对这个问题。

上一页123456下一页
软件测试工具 | 联系我们 | 投诉建议 | 诚聘英才 | 申请使用列表 | 网站地图
沪ICP备07036474 2003-2017 版权所有 上海泽众软件科技有限公司 Shanghai ZeZhong Software Co.,Ltd