JUnit4 使用指南三 (Runner 特性分析)

JUnit4 使用指南三 (Runner 特性分析)


Admin
2011年5月28日
大家有没有想过这个问题:当你把测试代码提交给 JUnit 框架后,框架如何来运行你的代码呢?答案就是 ——Runner 。在 JUnit 中有很多个 Runner ,他们负责调用你的测试代码,每一个 Runner 都有各自的特殊功能,你要根据需要选择不同的 Runner 来运行你的测试代码。可能你会觉得奇怪,前面我们写了那么多测试,并没有明确指定一个 Runner 啊?这是因为 JUnit 中有一个默认 Runner ,即 BlockJUnit4ClassRunner ,如果你没有指定,那么系统自动使用默认 Runner 来运行你的代码。

以第一章节的测试代码为例:



   
   
package com.rigel.ut; import org.junit.Test; public class CalculatorTest { @Test public void testAdd() { // ... } }


这段代码相当于:



   
   
package com.rigel.ut; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.internal.runners. BlockJUnit4ClassRunner ; @RunWith( BlockJUnit4ClassRunner . class ) public class CalculatorTest { @Test public void testAdd() { // ... } }




一般情况下,默认测试运行器可以应对绝大多数的单元测试要求;当使用 JUnit
提供的一些高级特性(例如即将介绍的两个特性)或者针对特殊需求定制JUnit测试方式时,显式的声明测试运行器就必不可少了。在Junit4
中,Junit为我们定义好了一些运行器,他们的层次结构如下:





















其中 ParentRunner是一个抽象类,包含了一个Runner的List,可以负责多个Runner运行。 Suite
一个测试套,继承了ParentRunner。BlockJUnit4ClassRunner则是Juint4默认的运行器,叫成Block是因为他是按
顺序一个一个执行测试用例的,Junit4中没有提供实现多线程执行的运行器。Junit4这个运行器只是单纯继承了
BlockJUnit4ClassRunner没有对其进行更改,并且它是final类型的,不允许继续被继承。 Enclosed是实现内部类的测试类的运行器。 Parameterized则可以设置参数化的执行测试用例。JUnit38ClassRunner是为了向后兼容JUnit3而定义的运行器。你也可以继承上面的类来实现新的运行器和注解功能。下面我们主要对 Parameterized及Suite Runner进行介绍。

1. Parameterized Runner 实现参数化测试


为了保证单元测试的严谨性,我们模拟了不同的测试数据来测试方法的处理能力,为此我们编写了大量的单元测试方法。这些测试方法都是大同小异:代码结构都是相同的,不同的仅仅是测试数据和期望值,为了解决这个问题,JUnit4提供了参数化测试。


举个简单的例子,比如我们需要对Calculator的加法功能进行测试,我们需要考虑“正数+正数”、“正数+负数”、“负数+负数”等等情况,因此我们可能需要像下面的代码那样写多个自己的测试方法:



    
    
package com.rigel.ut; import org.junit.Assert; import org.junit.Test; public class AddTest { private Calculator calc = new Calculator(); @Test public void testAdd1() { calc.add( 1 , 4 ); int result = 5 ; Assert.assertEquals(result, calc.getResult()); } @Test public void testAdd2() { calc.add( - 1 , - 4 ); int result = - 5 ; Assert.assertEquals(result, calc.getResult()); } // any other test methods // ... }


这些测试方法内容相同,仅仅只是测试数据有差异而已,写很多Test方法,其实是比较让人纠结的。 而JUnit4提出的“参数化测试”,可以只写一个测试函数,把这若干种情况作为参数传递进去,一次性的完成测试。代码实现如下:



    
    
package com.rigel.ut; import java.util.Arrays; import java.util.Collection; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; @RunWith(Parameterized. class ) public class AddTest { private int result; private int param1; private int param2; /** * 存放需要进行测试的数据集合 * */ @Parameters @SuppressWarnings( " rawtypes " ) public static Collection prepareData() { Object[][] data = {{ 5 , 1 , 4 }, { - 3 , 1 , - 4 }, { - 5 , - 1 , - 4 }}; return Arrays.asList(data); } /** * 对变量进行初始化 * */ public AddTest( int result, int param1, int param2) { this .result = result; this .param1 = param1; this .param2 = param2; } @Test public void addTest1() { Calculator calc = new Calculator(); calc.add(param1, param2); Assert.assertEquals(result, calc.getResult()); } }




代码的实现过程大致如下。首先,因为是采用了参数化测试,这时候TestCase所采用的Runner已经不再是系统默认的Runner,所
以,在类的定义处,必须通过@RunWith注解指定该TestCase采用的是Parameterized.class
Runner;其次,因为需要设定你的测试数据集合,主要是通过@parameters注解标注的 prepareData
方法来实现的,其返回的便是一个包含测试数据及测试结果的数据集合;最后需要定义该测试类的参数初始化过程,即需要制定其定义的参数是如何与设定的测试数
据集合中的数据对应上。在此基础上,便可以利用定义的参数来写你的测试方法,这样只需要定义一次@Test注解的测试方法,就可以把所有的测试数据都跑一
遍了。其最后测试结果如下:



2. Suite Runner 实现打包测试

一般在一个项目中,只写一个测试类是不可能的,我们会写出很多很多个测试类。如何这些测试类必须一个一个的执行,也是非常麻烦的事情。鉴于此,JUnit为我们提供了打包测试的功能,将所有需要运行的测试类集中起来,一次性的运行完毕,这大大的方便了我们的测试工作。



了方便说明,我们分开在两个测试类 AddTest &
SubstractTest中,分别测试Calculator的加法及减法功能,然后使用Suite
Runner实现一次Run两个TestCase。其中AddTest源代码同上,而SubstractTest代码如下:



     
     
package com.rigel.ut; import org.junit.Assert; import org.junit.Test; public class SubstractTest extends SupperTest{ private Calculator calc = new Calculator(); @Test public void testSubstract() { int result = 5 ; calc.substract( 10 , 5 ); Assert.assertEquals(result, calc.getResult()); } }



实现打包测试的TestCase取名“SuiteTest”,其代码实现如下:



     
     
package com.rigel.ut; import org.junit.runner.RunWith; import org.junit.runners.Suite; @RunWith(Suite. class ) @Suite.SuiteClasses({AddTest. class , SubstractTest. class }) public class SuiteTest { }




从“SuiteTest.java”源代码可以看出,该测试类没有任何实现,其只是通过@RunWith注解标识测试采用的Runner为
Suite
Runner,另外通过@Suite.SuiteClasses注解将所有需要进行测试的类打包进来。最后SuiteTest的测试结果如下:



从图中可以很清晰的看到打包测试的具体情况。总结一下,本章节主要对JUnit4的Runner特性进行了简单的介绍,重点介绍了其中的参数化测试与打包测试的实现。本章节到此结束。谢谢。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值