基于Eclipse的单元测试框架Junit进阶
导言
在学习了上篇入门之后,如果你有所尝试,相信已经把持不住想要更高级的功能了,下面我们进入正题。(先把上次的简介部分放过来,因为这次会用到Before和After)
Junit简介
JUnit是一个Java语言的单元测试框架,应用它进行单元测试,能够准确、快速地保证程序基本模块的正确性。Junit通过注解的方式来识别测试方法,目前支持的主要注解有:
- @BeforeClass:一次性setup,全局只执行一次,第一个运行
- @AfterClass:一次性teardown,全局也只执行一次,最后一个运行
- @Before:每次都在测试方法运行之前运行
- @After:每次都在测试方法运行之后运行
- @Test:测试方法
一个JUnit4的单元测试用例执行顺序为:
@BeforeClass -> @Before -> @Test -> @After -> @AfterClass,其中黑体部分可被多次执行。
添加Before&After
这个比较简单,只需要在新建测试程序的时候添加两个小选项就好,如图所示。
那么,这两个方法是做什么的呢?setUp()顾名思义,就是在每次测试开始之前要做的一些初始化工作,比如,清空队列、还原执行状态等;而tearDown()呢?也很容易理解,就是在某个testcase结束之后所做的一些回收、清除或者恢复工作。总之都是为了保证测试的高效进行。
测试异常处理
有时候我们的方法会抛出异常,那么测试的时候如果遇到会发现testcase显示为error,但是我们正是想让程序在某种情况下抛出异常,该如何处理呢?很简单,只需要添加一个expected就可以解决啦!
@Test(expected = ArithmeticException.class)
public void testDivideByZero(){
cal.divide(0);
}
这样,测试起来关于异常的error就可以消失不见了。
参数化测试
在某方法的分支较多、或者该方法的参数分很多情况、或者参数有较多特殊值,但是又需要较高的测试覆盖率时,我们就需要用到这种参数化的测试了,因为不然你的代码量会急剧飙升,而且会产生很多重复代码段,对于有程序洁癖的你是否能忍受呢?
我们还是举之前的例子,比如要测试乘方,我们也许会分3类测试:正数的平方,0的平方,负数的平方。如何参数化呢?
package JunitTest;
import static org.junit.Assert.*;
import java.util.Arrays;
import java.util.Collection;
import org.junit.Before;
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 ParaTest {
private static Calculator Cal = new Calculator();
private double para; //parameter passed to method
private double expcted; //expected result
@Before
public void setUp() throws Exception {
Cal.clear();
}
@Parameters
public static Collection db(){
return Arrays.asList(new Object[][]{
/*{para, expected}*/
{-6, 36},
{0, 0},
{3, 9}
});
}
public ParaTest(double para, double expected) {
// TODO Auto-generated constructor stub
this.para = para;
this.expcted = expected;
}
@Test
public void testSquare() {
Cal.square(this.para);
assertEquals(this.expcted, Cal.getResult(), 0.0001);
}
}
当然,这只是一个特例,在实际应用的时候不一定仅仅只有两个参数,也不一定一个参数是结果的期望值,总之灵活使用Collection中的东西就好,但切记,参数一定要按顺序书写,把握好db()和构造方法中的参数对应关系。
那么,这段代码如何实现的呢?做如下分析:
- 每一个参数化测试都要有自己的专属类,不能共用
- 为此类指定Runner为ParameterizedRunner,通过在类的声明处添加
@RunWith(Parameterized.class)
修饰来实现 - 在专属类中确定定义要使用的变量,该例有两个变量(para、expected)
- 用Collection框架让测试数据组的处理标准化,用
@Parameters
对其修饰 - 构造函数(constructor)的定义,保证与方法db()中参数的对应关系
限时测试
一般情况下,在测试时间过长、或者测试出现停滞状况时,我们都能够从JUnit的布局(layout)中看出来,从而定位到出现耗时较多(一般为死循环)的方法。所以该测试方式的作用主要体现在预防层面,而并非测试层面,这里就不赘述了。该方式可通过在注解@Test
之后添加timeout来实现: @Test(timeout = 1000)
,注意此处的time单位为毫秒(ms)。
以上就是我学到的JUnit应用,之后会有覆盖率统计相关的更新。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接(http://www.cnblogs.com/Echo-41/p/6921252.html)