`

JUnit4 详解

    博客分类:
  • Test
阅读更多

标准的Junit4流程及实现
我们先看一个标准的Junit4的运行流程,大致如下:
测试类实例化->运行@BeforeClass->运行@Before->运行@Test->运行@After->运行@AfterClass,
下面的代码输出明确表明了其运行流程,初学者可运行查看其结果输出。
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

public class Junit4Sample {
@BeforeClass
public static void beforeClass(){
System.out.println("BeforeClass,to be run once before any of the test methods in the class");
}

@Before
public void before(){
System.out.println("Before,to be run before the {@link org.junit.Test} method");
}

@Test
public void testA(){
System.out.println("Test,can be run as a test case");
}

@Test
public void testB(){
System.out.println("Test,can be run as a test case");
}

@After
public void after(){
System.out.println("After,to be run after the {@link org.junit.Test} method");
}

@AfterClass
public static void afterClass(){
System.out.println("AfterClass,to be run after all the tests in the class have been run");
}
}


这样的流程是怎么实现的呢?也就说Junit4.5+版本是如何处理这些Annotation并赋予了他们神奇的魔力的?请看大屏幕:

上图略去了其他次要方法,总之run方法还是入口,绕了一大圈后会调用with打头的方法处理流程中的@Before、@After等Annotation。

值得注意的是每个这样的方法都会有个Statement参数,封装了前一个流程中的Statement,其返回者也是个Statement供下个流程节点调用,就像个管道,Statement在管道里流啊流,管道里有一些点对流经的Statement进行特定处理。

通常情况下,Junit提供的Annotation已经很能满足需求了,这些注解其实就是对公用代码的一种抽象,比如要在每个测试用例方法执行前要执行一段代码就把他们提取出来为单独的方法并用@Before注解即可。可是,当有些问题很普遍很通用时懒人们不想在程序里写这样的Before方法了,比如配置文件的加载,测试前置数据装载等。

于是,就出现了更多的自定义的Annotation,怎么把这些自定义的Annotation功能嵌入到Junit的标准流程中呢?

 

 

=============================================================================

JUnit为我们在项目测试中常用到的单元测试框架,很多程序员的理想套件,本篇文章主要介绍JUnit4的常见annotation.

一、初始化标注

在老Junit4提供了setUp()和tearDown(),在每个测试函数调用之前/后都会调用。

@Before: Method annotated with @Before executes before every test.
@After:   Method annotated with @After executes after every test.

 

如果在测试之前有些工作我们只想做一次,用不着每个函数之前都做一次。比如读一个很大的文件。那就用下面两个来标注:

@BeforeClass
@AfterClass

注意:

@Before/@After 可以有多个; @BeforeClass/@AfterClass 只有一个

如果我们预计有Exception,那就给@Test加参数:

@Test(expected = XXXException.class)

 

如果出现死循环怎么办?这时timeout参数就有用了:

@Test(timeout = 1000)

 

如果我们暂时不用测试一个用例,我们不需要删除或都注释掉。只要改成:

@Ignore

你也可以说明一下原因@Ignore("something happens")

 

二、运行原理:

JUnit运行时都是由一个runner运行的。你可以根据需要选择不同的Runner来运行你的测试代码。指定一个Runner,需要使用@RunWith标注,并且把你所指定的Runner作为参数传递给它。系统自动使用默认Runner TestClassRunner来运行你的代码。如下:

@RunWith(TestClassRunner.class)

public class JavaTest { …… }

 

JUnit4提出了"参数化测试"的概念,只写一个测试函数,把这若干种情况作为参数传递进去,一次性的完成测试。代码如下:

 

@RunWith(Parameterized.class)
public class JavaTest {
private int param;
private int param2;
private int result;

 @Parameters public static Collection data() {
return Arrays.asList(new Object[][]{ { 2, 4, 6 }, { 0, 0, 0 }, { -3, 9, 6 } });
}

 // 构造函数,对变量进行初始化
public JavaTest(int param, int param2, int result) {
this.param = param;
this.param2 = param2;
this.result = result;
}

@Test public void run() {
//do some thing use args, and assert it
int expected = param + param2;
assertEquals(expected, result);
}
@Ignore("lala") public void lala() {
assertEquals(3,3);
}
} 


首先,你要为这种测试专门生成一个新的类,为这个类指定一个Runner,特殊的功能要用特殊的Runner:@RunWith(Parameterized.class)
第二步,定义测试数据的集合,也就是上述的data()方法,该方法可以任意命名,但是必须使用@Parameters标注进行修饰。这是一个二维数组,每组数据产生一个测试Instance.
第三步,构造函数,取得传过来的参数。
最后,用取得的参数做测试。@Test public void …

 

三、打包测试:

采取分而治之的方法,我们可以写多个类来降低测试难度。我们有时也希望一次把所有测试跑一遍,这时我们写一个打包类

import junit.framework.JUnit4TestAdapter;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;

 

@RunWith(Suite.class)
@Suite.SuiteClasses({
JavaTest.class,
JustDo.class
})
public class TestAll {
}

 

四、多线程测试

      JUnit4的Test写好以后,对于一些集成度比较高的测试用例,还希望完成并发访问情况下的测试,但是,JUnit4缺省情况没有提供,我希望通过自己写一个main函数,然后创建几个线程,在几个线程中同时运行测试用例进行测试,来模拟并发访问的情况,下里为具体例子:

public class TestExample {

@Test
public void testMethod() {
System.out.println("test success!");
}
}

public class PerfomanceTest {

public static void main(String[] args) {
new Thread() {public void run() {

// JUnitCore.runClasses(new Class[] { TestExample.class });           (1)
// new JUnitCore().run(Request.method(TestExample.class, "testMethod"));        (2)
}}.start();
}
}

注:标志1或标志2中只要用一种就可以测试。

到这里,我们就可以使用JUnit4来开发我们自己的测试了。

 


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics