在项目中,我们经常会使用到JUnit单元测试,那么我们今天就来看看JUnit到底有那些用法;
1, 说到JUnit首先要了解一下它的母亲--xUnit, xUnit是一套基于测试驱动开发的测试框架,派生出许多子类框架,有专门测试C++的 CppUnit,Python的PythonUnit和我们专门测试JAVA的JUnit;
注意 : 测试用例不是用来证明你是对的,而是证明你没有错!
2, 测试框架的作用:
(1), 帮助我们对编写的程序进行有目的的测试;
(2), 帮助我们最大限度的避免代码中的BUG,并使程序达到预期效果;
3, 书写规范:
(1), 测试方法上必须使用 @Test 进行修饰;
(2), 测试方法必须使用 public void 进行修饰,并且不能带任何参数;
(3), 新建一个源码目录(test)来存放测试代码;
(4), 测试类的包名必须与被测试的包名相同;
(5), 测试单元中的每个方法必须可以独立测试,测试方法间不能有任何依赖;
(6), 测试类使用 Test 作为类名的前缀;
(7), 测试方法使用 test 作为方法名的后缀;
4, 测试失败的两种情况;
(1), 测试失败: Failure 一般有单元测试使用的断言方法判断失败所引起的,它表示测试点发现了问题,就是说程序输出的结果和我们预期的结果不同;
(2), 测试错误: Errors 由代码异常引起的,它可以产生于测试代码本身的错误,也可以是测试代码中被隐藏的BUG;
注意 : 测试用例不是用来证明你是对的,而是证明你没有错!
5, JUnit4的运行流程:
package test;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class MyJUnitTest1 {
@BeforeClass
public static void setUpBeforeClass() throws Exception {
System.out.println("this is @BeforeClass");
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
System.out.println("this is @AfterClass");
}
@Before
public void setUp() throws Exception {
System.out.println("this is @Before");
}
@After
public void tearDown() throws Exception {
System.out.println("this is @After");
}
@Test
public void test() {
System.out.println("this is @Test");
}
@Test
public void test2() {
System.out.println("this is @Test2");
}
/**
* 运行结果 :
* this is @BeforeClass 所有方法之前运行;
*
this is @Before 每个方法之前运行;
this is @Test
this is @After 每个方法之后运行;
this is @Before
this is @Test2
this is @After
this is @AfterClass 所有方法之后运行;
*
* */
}
(1), @BeforeClass 修饰的方法会在该测试类的所有方法调用之前调用,而且该方法是静态的,所以当测试类被加载后,接着就会运行它,而且内存中它只会存在一份实例, 比较适合加载配置文件;
(2), @AfterClass 所修饰的方法通常用来对资源的释放,如关闭数据库的连接,在所有方法之后调用;
(3), @Before 每个方法之前调用;
(4), @After 每个方法之后调用;
6: 常用注解:
package test;
import static org.junit.Assert.*;
import org.junit.Ignore;
import org.junit.Test;
public class MyJUnitTest2 {
private int add(int a, int b){
return a+b;
}
@Test(expected=AssertionError.class)
public void test() {
//JUnit4中的断言方法:
assertEquals(3,add(6,2));
}
@Test(timeout=1000)
public void test1() {
while(true){
System.out.println("Hello world");
}
}
@Ignore
@Test
public void test2() {
while(true){
assertEquals(3,add(6,2));
}
}
/**
* 除了之前的注解外,还有:
* 1: @Test(expected=AssertionError.class) 预测会抛出 AssertionError.class 异常
*
* 2: @Test(timeout=毫秒) 控制测试时间,防止死循环,可以性能测试;
*
* 3: @Ignore 所修饰的测试用例会被运行器自动忽略;
*
* 4: @RunWith 更改测试运行器;
* */
}
7, JUnit4 测试套件:
package test;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
@SuiteClasses({MyTest.class,MyTest2.class,MyJUnitTest1.class})
public class MyJUnitSuiteTest {
}
/**
* 测试套件: 就是组织测试测试类一起运行,方便我们批量测试;
* 测试套件入口类,必须为空类;
* @RunWith(Suite.class) : 更改测试运行器为Suite.class;
* @SuiteClasses({MyTest.class,MyTest2.class,MyTest1.class}) : 放入需要测试的测试类数组
*
* */
8, JUnit4 参数化设置:
package test;
import static org.junit.Assert.*;
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;
/**
*@description TODO 参数化设置测试类
*@date 2018/1/7
*@author geYang
**/
@RunWith(Parameterized.class)
public class MyJUnitParamTest {
/**
* 1, 更改默认的运行测试器为 @RunWith(Parameterized.class);
* 2, 声明变量存放预期值和结果值,
* 3, 声明一个返回值为 Collection 的公共静态方法,并且使用 @Parameters 修饰;
* 4, 创建带参构造器,为声明的变量赋值;
* */
private int expected = 0;
private int param1 = 0;
private int param2 = 0;
@Parameters
public static Collection t(){
return Arrays.asList(new Object[][]{
{3,2,1},
{4,2,2},
{6,3,3}
});
}
public MyJUnitParamTest(int expected, int param1, int param2) {
this.expected = expected;
this.param1 = param1;
this.param2 = param2;
}
private int add(int a,int b){
return a+b;
}
@Test
public void test() {
assertEquals(expected, add(param1,param2));
}
}
有了这么多的注解和方法,相信在以后的项目开发过程中,可以更容易的书写测试用例.