必要的包
- org.junit.*
- import static org.junit.Assert.*;
- 可选的Hamcrest
Annotation注解/元数据(描述数据的数据)
- @BeforeClass 在类被装载的时候就被调用(还未创建实例),所以需要static方法,还需要public,且每个类仅能有一个
- @AfterClass
- @Before 每个测试方法前都要执行一次,可以用于把对象复原,以免对其他测试造成影响。这个相当于取代了JUnit以前版本中的setUp方法
- @After,这个相当于取代了JUnit以前版本中的tearDown方法
- @Test 返回值必须是void,而且无参数
- @Ignore(“该方法还没有实现”) ,String参数,表明为什么会忽略这个测试方法。该注解加在@Test上一行,在执行的时候,仅会报告该方法没有实现,而不会运行测试方法。当测试的方法还没有实现,或者测试的方法已经过时,或者在某种条件下才能测试该方法(比如需要一个数据库联接,而在本地测试的时候,数据库并没有连接)。
- @Test(timeout = xxx) 该元数据传入了一个时间(毫秒)给测试方法,限制测试,超时则失败,对于逻辑很复杂,循环嵌套深,可能出现死循环的程序,可采取此预防措施
- @Test(expected = *.class)使用@Test标注的expected属性,将我们要检验的异常传递给他,这样JUnit框架就能自动帮我们检测是否抛出了我们指定的异常。
@Test(expected = ArithmeticException.class)
public void divideByZero() {
calculator.divide(0);
}
- @Paramenters 用于参数化测试
Assert类中常用方法
- assertEquals()
- assertFalse()
- assertTure()
- assertNull()
- assertNotNull()
- assertSame()
- assertNotSame()
- 结合Hamcrest,使用assertThat([value]), [matcher statement])方法可以实现更灵活的断言判断,需要引入hamcrest的jar包
Hamcrest的使用
is匹配符表明如果前面待测的object等于后面给出的object,则测试通过
assertThat( testedObj, is( object) );containsString匹配符表明如果测试的字符串包含指定的子字符串则测试通过
assertThat( testedString, containsString( "developerWorks" ) );greaterThan匹配符表明如果所测试的数值testedNumber大于16.0则测试通过
assertThat( testedNumber, greaterThan(16.0) );closeTo匹配符表明如果所测试的浮点型数testedDouble在20.0±0.5范围之内则测试通过
assertThat( testedDouble, closeTo( 20.0, 0.5 ) );hasItem匹配符表明被测的迭代对象含有元素element项则测试通过assertThat(iterableObject, hasItem (element));
参数化测试
把测试代码提交给JUnit框架后,框架如何来运行代码呢?答案就是——Runner。在JUnit中有很多个 Runner,他们负责调用测试代码,每一个Runner都有各自的特殊功能,要根据需要选择不同的Runner来运行测试代码。JUnit中有一个默认Runner,如果没有指定,那么系统自动使用默认 Runner来运行你的代码。
参数化测试,需要的runner就不是默认的了。@RunWith(Parameterized.class)这条语句就是为这个类指定了一个ParameterizedRunner。第二步,定义一个待测试的类,并且定义两个变量,一个用于存放参数,一个用于存放期待的结果。
除此之外,还用到了注解@Paramenters,定义测试数据的集合,也就是上述的data()方法,该方法可以任意命名,但是必须使用@Parameters标注进行修饰。其中的数据是一个二维数组,数据两两一组,每组中的这两个数据,一个是参数,一个是你预期的结果。比如我们的第一组{2, 4},2就是参数,4就是预期的结果。这两个数据的顺序无所谓,谁前谁后都可以。之后是构造函数,其功能就是对先前定义的两个参数进行初始化。 在这里你可要注意一下参数的顺序了,要和上面的数据集合的顺序保持一致。如果前面的顺序是{参数,期待的结果},那么你构造函数的顺序也要是“构造函数(参数, 期待的结果)”,反之亦然。
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 CalculatorTest2{
private Calculator cal = new Calculator();
private int param;
private int result;
//构造函数,对变量进行初始化
//定义一个待测试的类,并且定义两个变量,一个用于存放参数,一个用于存放期待的结果。
public CalculatorTest2(int param, int result) {
this.param = param;
this.result = result;
}
@Parameters
public static Collection data(){
return Arrays.asList(new Object[][]{
{2, 4},
{0, 0},
{-3, 9},
});
}
@Test
public void squareTest() {
int temp = cal.square(param);
Assert.assertEquals(result, temp);
}
}
打包测试
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
/**
* 大家可以看到,这个功能也需要使用一个特殊的Runner,
* 因此我们需要向@RunWith标注传递一个参数Suite.class。
* 同时,我们还需要另外一个标注@Suite.SuiteClasses,
* 来表明这个类是一个打包测试类。我们把需要打包的类作为参数传递给该标注就可以了。
* 有了这两个标注之后,就已经完整的表达了所有的含义,因此下面的类已经无关紧要,
* 随便起一个类名,内容全部为空既可
*
*/
@RunWith(Suite.class)
@Suite.SuiteClasses({ CalculatorTest.class, CalculatorTest2.class })
public class AllCalculatorTests {
}
断言和假设
断言:org.junit.Assert用于测试用例中,如果断言失败,用例即结束。
假设:org.junit.Assume用于在准备环境时判断环境是否符合要求,包括测试类的@BeforeClass,测试类的实例化,测试类的@Before。
如果假设失败,假设所处初始化代码方法立即结束,更深级别的后续工作也被忽略,相关测试用例被忽略,但与假设同级别的收尾工作还要继续执行。
参考:
http://tonl.iteye.com/blog/1948869
http://blog.csdn.net/andycpp/article/details/1329218