junit4学习心得

简介

JUnit迅速成为Java中开发单元测试的串实上的标准框架。被称为xUnit的相关测试框架,正在逐渐成为任何语言的标准框架。ASP、C++,C#、Eiffel.Delphi、Perl、PHP、Python、REBOL.Smalltalk和VisualBasic都有了对应的xUnit框架,这里只是列举了一些而已。

用处和特点

断言

junit 断言方法示例

  • assertArrayEquals
  • assertEquals : 调用equals方法比较两个对象
  • assertSame: 调用== 比较两个对象,相当于比较两个对象是否使用同一个内存地址
  • assertTrue: 判断 true
  • assertNotNull 断言A对象不为null

Test Runners

暂时看文档没有找到合适的解释

聚集测试套件

把suites放在Runwith注解中,可以组建一个包含多个测试类在内的测试套件。
兼容junit4.0和junit3.8.x

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

@RunWith(Suite.class)
@Suite.SuiteClasses({
  TestFeatureLogin.class,
  TestFeatureLogout.class,
  TestFeatureNavigate.class,
  TestFeatureUpdate.class
})

public class FeatureTestSuite {
  // the class remains empty,
  // used only as a holder for the above annotations
}

按顺序进行测试

import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestMethodOrder {

    @Test
    public void testA() {
        System.out.println("first");
    }
    @Test
    public void testB() {
        System.out.println("second");
    }
    @Test
    public void testC() {
        System.out.println("third");
    }
}

测试异常

@Test(expected = IndexOutOfBoundsException.class) 
public void empty() { 
     new ArrayList<Object>().get(0); 
}

正则匹配和断言结合

assertThat(x, is(3));
assertThat(x, is(not(4)));
assertThat(responseString, either(containsString("color")).or(containsString("colour")));
assertThat(myList, hasItem("3"));

assertThat([value], [matcher statement]);

忽略类中已经测试过的类

@Ignore("Test is ignored as a demonstration")
@Test
public void testSame() {
    assertThat(1, is(1));
}

给测试加上超时时间

@Test(timeout=1000)
public void testWithTimeout() {
  ...
}

参数化的测试

import static org.junit.Assert.assertEquals;

import java.util.Arrays;
import java.util.Collection;

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 FibonacciTest {
    @Parameters
    public static Collection<Object[]> data() {
        return Arrays.asList(new Object[][] {     
                 { 0, 0 }, { 1, 1 }, { 2, 1 }, { 3, 2 }, { 4, 3 }, { 5, 5 }, { 6, 8 }  
           });
    }

    private int fInput;

    private int fExpected;

    public FibonacciTest(int input, int expected) {
        fInput= input;
        fExpected= expected;
    }

    @Test
    public void test() {
        assertEquals(fExpected, Fibonacci.compute(fInput));
    }
}

Fibonacci函数如下:

public class Fibonacci {
    public static int compute(int n) {
        int result = 0;

        if (n <= 1) { 
            result = n; 
        } else { 
            result = compute(n - 1) + compute(n - 2); 
        }

        return result;
    }
}

提供了假设机制的断言

假设机制使用举例:
例1:

@Test 
public void filenameIncludesString() {
    //如果文件分隔符不是’/’(forward slash),则不执行assertThat断言测试,直接跳过该测试用例函数
    assumeThat(File.separatorChar, is('/'));
    //判断文件名fileName是否含有字符串"developerWorks"
    assertThat( fileName, containsString( "developerWorks" ) );
}

例2:

@Test 
public void filenameIncludesString() {
    //bugFixed不是JUnit4.4的函数,是开发人员自己工程中定义的函数,表示判断指定的defect是否
    //被修正了,如果被修正,则返回true,否则返回false。这里假设缺陷13356被修正后才进行余下单元测试
    assumeTrue( bugFixed("13356") ); 
    //判断文件名fileName是否含有字符串"developerWorks"
    assertThat( fileName, containsString( "developerWorks" ) );
}

rules

  • 在运行测试之前,能够得到测试名以做一些需要的处理
  • 指导Swing来运行测试
  • 对测试失败的case加入额外信息作为参考,尤其对于selenium有作用,如抓屏

提供了理论机制的断言

import static org.hamcrest.Matchers.*; //指定接下来要使用的Matcher匹配符
import static org.junit.Assume.*; //指定需要使用假设assume*来辅助理论Theory
import static org.junit.Assert.*; //指定需要使用断言assert*来判断测试是否通过

import org.junit.experimental.theories.DataPoint;   //需要使用注释@DataPoint来指定数据集
import org.junit.experimental.theories.Theories; //接下来@RunWith要指定Theories.class 
import org.junit.experimental.theories.Theory; //注释@Theory指定理论的测试函数
import org.junit.runner.RunWith; //需要使用@RunWith指定接下来运行测试的类

import org.junit.Test;

//注意:必须得使用@RunWith指定Theories.class
@RunWith(Theories.class)
public class TheoryTest {

//利用注释@DataPoint来指定一组数据集,这些数据集中的数据用来证明或反驳接下来定义的Theory理论,
//testNames1和testNames2这两个理论Theory测试函数的参数都是String,所以Junit4.4会将这5个
//@DataPoint定义的String进行两两组合,统统一一传入到testNames1和testNames2中,所以参数名year
//和name是不起任何作用的,"2007"同样有机会会传给参数name,"Works"也同样有机会传给参数year
@DataPoint public static String YEAR_2007 = "2007";
@DataPoint public static String YEAR_2008 = "2008";
@DataPoint public static String NAME1 = "developer";
@DataPoint public static String NAME2 = "Works";
@DataPoint public static String NAME3 = "developerWorks";

//注意:使用@Theory来指定测试函数,而不是@Test
@Theory 
public void testNames1( String year, String name ) {
    assumeThat( year, is("2007") ); //year必须是"2007",否则跳过该测试函数
    System.out.println( year + "-" + name );
    assertThat( year, is("2007") ); //这里的断言语句没有实际意义,这里举此例只是为了不中断测试
}

//注意:使用@Theory来指定测试函数,而不是@Test
@Theory
public void testNames2( String year, String name ) {
    assumeThat(year, is("2007")); //year必须是"2007",否则跳过该测试函数
    //name必须既不是"2007"也不是"2008",否则跳过该测试函数
    assumeThat(name, allOf( not(is("2007")), not(is("2008"))));
    System.out.println( year + "-" + name );
    assertThat( year, is("2007") ); //这里的断言语句没有实际意义,这里举此例只是为了不中断测试
}






结果输出:
第一个Theory打印出:
2007-2007
2007-2008
2007-developer
2007-Works
2007-developerWorks
第二个Theory打印出:
2007-developer
2007-Works
2007-developerWorks

分组测试

public class A {  
    @Test  
    public void a() {  
        fail();  
    }  

    @Category(SlowTests.class)  
    @Test  
    public void b() {         
        System.out.println("A b()");  
    }  
}  


    @Category( { SlowTests.class, FastTests.class })  
    public class B {  
    @Test  
    public void c() {  
        System.out.println("B c()");  
    }  
} 

@RunWith(Categories.class)//这个地方与一般的套件测试有所不同  
@IncludeCategory(SlowTests.class)  
@SuiteClasses( { A.class, B.class }) // Note that Categories is a kind of Suite  
public class SlowTestSuite {  

  // Will run A.b and B.c, but not A.a  

} 

未介绍的功能

  • Test Fixtures
  • Use with Maven
  • Multithreaded code and Concurrency
  • Java contract test helpers
  • Continuous Testing

参考

junit官网

Junit in Action 中文版

欢迎大家关注:huazi's微信公众号