Junit是我们编写Java 测试用例时候常用的方式。Junit4为我们提供了非常方便的单元测试,参数化测试,以及组合单元测试。
Junit4安装:下载Junit4 jar包,导入项目
一、常用注解解释:
1. @Test注解
@Test注解是我们最常见的注解,用于标注一个函数是测试函数,如下所示:
@Test
public void test() {
assertEquals(3,1+2);
}
@Test提供两种参数,分别为expected和timeout
expected = XXX.class 表示希望测试函数抛出某个异常
@Test(expected = IndexOutOfBoundsException.class)
public void test(){
new ArrayList<Object>().get(1);
}
timeout = 1000 表示测试函数的最大运行时间是1000ms 超出这个时间则报错
@Test(timeout = 2000)
public void test() throws InterruptedException{
Thread.sleep(1000);
}
2. @BeforeClass,@Before,@After,@AfterClass
@Before 和 @After均是对于方法级别的注解
@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
}
对于每个使用了@Test注解注释的测试函数,都必须在函数运行开始和结束的时候分别运行上述的函数
@Before->@Test->@After
@BeforeClass和@AfterClass是对于类级别的注解
@BeforeClass
public static void setUpBeforeClass() throws Exception {
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
}
在类初始化的时候进行一些初始化的操作例如数据库建立之类的,方法对应的是static的静态方法
@BeforeClass->@Before->@Test->@After->@AfterClass
3.
@Ignore 忽略一个测试方法或者测试类
@Ignore
@Test(timeout = 2000)
public void test() throws InterruptedException{
Thread.sleep(1000);
}
4. @RunWith
设置Junit测试用例的启动器。Runner负责调用你的测试代码,每一个Runner都有各自的特殊功能,根据需要选择不同的Runner来运行测试代码。Junit4默认设置的是@RunWith(BlockJunit4ClassRunner.class) 。
但是当我们进行参数化测试和组合单元测试的时候,我们需要使用其他的启动器。这个在下面再说
5. @SuiteClasses({A.class,B.class})
用于组合单元测试时候
二、参数化测试
什么叫参数化测试呢?我们看下面一个小例子:
@Test
public void testCheckTriangle() {
assertEquals(false,tri.checkTriangle(1,2,3));
assertEquals(true,tri.checkTriangle(3,4,5));
assertEquals(true,tri.checkTriangle(3,3,1));
assertEquals(true,tri.checkTriangle(2,2,2));
}
比如,当我们希望测试判断三角形的这个函数的时候?我们有四个例子,所以需要些四个例子
所谓参数化测试,就是我们将数据存储在某个数据结构之中,然后这个测试用例会自动加载这个数据结构,然后一个一个取出其中的记录,进行多个测试
那么我们应该怎么编写我们的测试用例呢?
1.首先新建一个测试类这里为TriangleTest.java
public class TriangleTest {
}
2.声明成员变量:我们的三条边分别为a,b,c 我们期望的结果是result
public class TriangleTest {
static Triangle tri;
private int a,b,c;
private boolean result;
}
3.编写构造函数:在构造函数中给四个成员变量赋值
public class TriangleTest {
static Triangle tri;
private int a,b,c;
private boolean result;
public TriangleTest(boolean result,int a,int b,int c)
{
this.result = result;
this.a = a;
this.b = b;
this.c = c;
}
@BeforeClass
public static void setUpBeforeClass() throws Exception {
tri = new Triangle();
}
}
4.编写加载数据的函数
@RunWith(Parameterized.class)
public class TriangleTest {
static Triangle tri;
private int a,b,c;
private boolean result;
public TriangleTest(boolean result,int a,int b,int c)
{
this.result = result;
this.a = a;
this.b = b;
this.c = c;
}
@BeforeClass
public static void setUpBeforeClass() throws Exception {
tri = new Triangle();
}
@Parameters
public static Collection<Object[]> getData()
{
List<Object[]> list = new ArrayList<>();
list.add(new Object[]{
false,1,2,3
});
list.add(new Object[]{
true,3,4,5
});
list.add(new Object[]{
true,2,2,2
});
list.add(new Object[]{
true,3,3,1
});
return list;
}
}
这里解释一下这个加载数据的函数:首先,这个函数要声明为static静态函数,同时要返回一个容器例如数组,或者列表之类的。那么为什么这个容器的类型是Object[]呢?
Object [] 表示的是你的一条数据记录。例如我们有一个测试是测试三角形3,4,5,期望结果是true 那么这个记录应该表示为:
Object obj = new Object[]{ true,3,4,5 });
使用Object以适应任意类型
5.编写测试函数
@Test
public void testParameter()
{
assertEquals(result,tri.checkTriangle(a, b, c));
}
6.设置测试类为参数化测试
@RunWith(Parameterized.class)
测试结果:
三、组合单元测试:
我们编写两个简单的测试类testa和testb
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
public class testa {
@Test
public void test() {
assertEquals(2,1+1);
}
}
import static org.junit.Assert.*;
import java.util.ArrayList;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
public class testb {
@Test
public void test(){
assertEquals(3,2+1);
}
}
然后编写一个组合单元测试,设置组合类为组合测试启动,设置组合类的内容
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
@SuiteClasses({testa.class,testb.class})
public class SuiteTest {
}
Harmcrest:在我测试的时候,使用的是junit-4.12+harmcrest-core-1.3+harmcrest-library-1.3。也可以使用harmcrest-all-1.3,相关jar在harmcrest官网下载
harmcrest为我们提供了以下常用的函数:
• allOf - matches if all matchers match (short circuits)
• anyOf - matches if any matchers match (short circuits)
• not - matches if the wrapped matcher doesn't match and vice versa
• equalTo - test object equality using the equals method
• is - decorator for equalTo to improve readability
• hasToString - test Object.toString
• instanceOf, isCompatibleType - test type
• notNullValue, nullValue - test for null
• sameInstance - test object identity
• hasEntry, hasKey, hasValue - test a map contains an entry, key or value
• hasItem, hasItems - test a collection contains elements
• hasItemInArray - test an array contains an element
• closeTo - test floating point values are close to a given value
• greaterThan, greaterThanOrEqualTo, lessThan, lessThanOrEqualTo - test ordering
• equalToIgnoringCase - test string equality ignoring case
• equalToIgnoringWhiteSpace - test string equality ignoring differences in runs of whitespace
• containsString, endsWith, startsWith - test string matching
下面是使用harmcrest的一个例子:
import org.junit.Assert;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
public class testa {
@Test
public void test() {
org.hamcrest.MatcherAssert.assertThat(40,allOf(greaterThan(20),lessThan(60)));
org.hamcrest.MatcherAssert.assertThat("abcdefg",allOf(startsWith("abc"),endsWith("efg")));
}
}
想要使用harmcrest的匹配函数,我们一般要引入如下库:
import static org.hamcrest.Matchers.*;
否则,无法使用上述的匹配库中的函数。
同时,你会看到,我在使用assertThat的时候,显示声明使用org.hamcrest.MatcherAssert.assertThat,这是为了和junit中的assertThat区分开
如果你在使用harmcrest时遇到这样的问题:
java.lang.NoSuchMethodError: org.hamcrest.core.AnyOf.anyOf(Lorg/hamcrest/Matcher;Lorg/hamcrest/Matcher;)Lorg/hamcrest/core/AnyOf;
一般这样的情况,是由于你的junit和harmcrest引入的包的顺序不对。要把harmcrest放在junit的前边,这样每次调用allof的时候才会使用harmcrest中的函数。
更改引入顺序,删除相应的junit重新导入,或者更换一下junit版本
P.S.文章不妥之处还望指正