JUnit_JUnit基本使用

参考JUnit入门教程(一), JUnit

Hello world

编写functional code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Calculator {   

public int plus(int x, int y) {
return x + y;
}
public int subtraction(int x, int y) {
return x - y;
}
public int multiplication(int x, int y) {
return x * y;
}
public int division(int x, int y) {
return x / y;
}
}

编写单元测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import static org.junit.Assert.*; //注意这边,静态导入  

import org.junit.Ignore;
import org.junit.Test;

import com.zjw.junit4.Calculator;

public class TestCalculator {

@Test
public void testPlus() {
Calculator cal = new Calculator();
assertEquals(cal.plus(5, 5), 10);
}

@Test
public void testSubtraction() {
Calculator cal = new Calculator();
assertEquals(cal.subtraction(5, 5), 0);
}

@Ignore
@Test
public void testMultiplication() {
Calculator cal = new Calculator();
assertTrue(cal.multiplication(5, 5) > 20);
}

@Test(expected = java.lang.ArithmeticException.class, timeout = 50)
public void testDivision() {
Calculator cal = new Calculator();
assertEquals(cal.division(8, 0), 4);
}
}

可以看到每个测试都创建了一个实例,但其实这是没有必要的,我们可以是使用@BeforeClass在所有测试方法执行之前创建实例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import static org.junit.Assert.*;  

import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;

import com.zjw.junit4.Calculator;

public class TestCalculator {

private static Calculator cal;

@BeforeClass
public static void beforeClass(){ //静态方法
cal=new Calculator();
}

@Test
public void testPlus() {
assertEquals(cal.plus(5, 5), 10);
}

@Test
public void testSubtraction() {
assertEquals(cal.subtraction(5, 5), 0);
}

@Ignore
@Test
public void testMultiplication() {
assertTrue(cal.multiplication(5, 5) > 20);
}

@Test(expected = java.lang.ArithmeticException.class, timeout = 50)
public void testDivision() {
assertEquals(cal.division(8, 0), 4);
}
}

测试

使用Elipse可以直接使用Run as的JUnit test。
也可以编码执行测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;

public class TestRunner {
public static void main(String[] args) {
Result result = JUnitCore.runClasses(TestCalculator.class);
for (Failure failure : result.getFailures()) {
System.out.println(failure.toString());
}
System.out.println(result.wasSuccessful());
}
}

一些JUnit 4的Annoation

  • @Test: 测试方法(expected=XXException.class, timeout=xxx)
  • @Ignore: 忽略测试方法
  • @Before: 每一个测试方法之前运行
  • @After: 每一个测试方法之后运行
  • @BeforeClass: 所有测试开始之前运行,别忘了方法是静态的,相当于JUnit 3中的setUp()方法。
  • @AfterClass: 所有测试结束之后运行,相当于JUnit 3中的tearDown()方法。

@Test设置了expected=XXException.class时,这个异常发生后,为测试成功。设置了timeout时,超过时间为测试失败。

Settings

  • 测试类放在test包中
  • 类名用TestXXX
  • 方法用test方法名命名

JUnit类

Junit 4可以是使用基于标注的方式来设置测试,但是同样可以使用继承TestCase。才外还有几个重要的JUnit类,虽然在JUnit 4中很多时候不必显示使用,但是必须要要了解。

一些重要的类如下:

功能
Assert assert 方法的集合
TestCase 一个定义了运行多重测试的固定装置
TestResult TestResult 集合了执行测试样例的所有结果
TestSuite TestSuite 是测试的集合

Assert

public class Assert extends java.lang.Object

这个类提供了一系列的编写测试的有用的声明方法。只有失败的声明方法才会被记录。Assert 类的重要方法列式如下:

方法 描述
void assertEquals(boolean expected, boolean actual) 检查两个变量或者等式是否平衡
void assertFalse(boolean condition) 检查条件是假的
void assertNotNull(Object object) 检查对象不是空的
void assertNull(Object object) 检查对象是空的
void assertTrue(boolean condition) 检查条件为真
void fail() 在没有报告的情况下使测试不通过
void assertArrayEquals(expectedArray, resultArray)
assertArrayEquals() 方法检查两个数组是否相等

TestCase 类

下面介绍的是 org.junit.TestCaset 类:

public abstract class TestCase extends Assert implements Test

测试样例定义了运行多重测试的固定格式。TestCase 类的一些重要方法列式如下:

方法 描述
int countTestCases() 为被run(TestResult result) 执行的测试案例计数
TestResult createResult() 创建一个默认的 TestResult 对象
String getName() 获取 TestCase 的名称
TestResult run() 一个运行这个测试的方便的方法,收集由TestResult 对象产生的结果
void run(TestResult result) 在 TestResult 中运行测试案例并收集结果
void setName(String name) 设置 TestCase 的名称
void setUp() 创建固定装置,例如,打开一个网络连接
void tearDown() 拆除固定装置,例如,关闭一个网络连接
String toString() 返回测试案例的一个字符串表示

TestResult 类

下面定义的是 org.junit.TestResult 类:

public class TestResult extends Object
TestResult类收集所有执行测试案例的结果。它是收集参数层面的一个实例。这个实验框架区分失败和错误。失败是可以预料的并且可以通过假设来检查。错误是不可预料的问题就像ArrayIndexOutOfBoundsException。

TestResult 类的一些重要方法列式如下:

方法 描述
void addError(Test test, Throwable t) 在错误列表中加入一个错误
void addFailure(Test test, AssertionFailedError t) 在失败列表中加入一个失败
void endTest(Test test) 显示测试被编译的这个结果
int errorCount() 获取被检测出错误的数量
Enumeration errors() 返回错误的详细信息
int failureCount() 获取被检测出的失败的数量
void run(TestCase test) 运行 TestCase
int int runCount() 获得运行测试的数量
void startTest(Test test) 声明一个测试即将开始
void stop() 标明测试必须停止

TestSuite 类

下面定义的是 org.junit.TestSuite 类:

public class TestSuite extends Object implements Test

TestSuite类是测试的组成部分。它运行了很多的测试案例。TestSuite 类的一些重要方法列式如下:

方法 描述
void addTest(Test test) 在套中加入测试。
void addTestSuite(Class<? extends TestCase> testClass) 将已经给定的类中的测试加到套中。
int countTestCases() 对这个测试即将运行的测试案例进行计数
String getName() 返回套的名称。
void run(TestResult result) 在 TestResult 中运行测试并收集结果。
void setName(String name) 设置套的名称。
Test testAt(int index) 在给定的目录中返回测试。
int testCount() 返回套中测试的数量。
static Test warning(String message) 返回会失败的测试并且记录警告信息。
1
2
3
4
5
6
7
8
9
10
import junit.framework.*;
public class JunitTestSuite {
public static void main(String[] a) {
// add the test's in the suite
TestSuite suite = new TestSuite(TestJunit1.class, TestJunit2.class, TestJunit3.class );
TestResult result = new TestResult();
suite.run(result);
System.out.println("Number of test cases = " + result.runCount());
}
}

测试

JUnitCore

测试用例是使用 JUnitCore 类来执行的。JUnitCore 是运行测试的外观类。它支持运行 JUnit 4 测试, JUnit 3.8.x 测试,或者他们的混合。 要从命令行运行测试,可以运行 java org.junit.runner.JUnitCore 。对于只有一次的测试运行,可以使用静态方法 runClasses(Class[])。

下面是 org.junit.runner.JUnitCore 类的声明:
public class JUnitCore extends java.lang.Object

套件测试

测试套件意味着捆绑几个单元测试用例并且一起执行他们。在 JUnit 中,@RunWith 和 @Suite 注释用来运行套件测试。这个教程将向您展示一个例子,其中含有两个测试样例 TestJunit1 & TestJunit2 类,我们将使用测试套件一起运行他们。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class MessageUtil {

private String message;

//Constructor
//@param message to be printed
public MessageUtil(String message){
this.message = message;
}

// prints the message
public String printMessage(){
System.out.println(message);
return message;
}

// add "Hi!" to the message
public String salutationMessage(){
message = "Hi!" + message;
System.out.println(message);
return message;
}
}

Test Case类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import org.junit.Test;
import org.junit.Ignore;
import static org.junit.Assert.assertEquals;

public class TestJunit1 {

String message = "Robert";
MessageUtil messageUtil = new MessageUtil(message);

@Test
public void testPrintMessage() {
System.out.println("Inside testPrintMessage()");
assertEquals(message, messageUtil.printMessage());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import org.junit.Test;
import org.junit.Ignore;
import static org.junit.Assert.assertEquals;

public class TestJunit2 {

String message = "Robert";
MessageUtil messageUtil = new MessageUtil(message);

@Test
public void testSalutationMessage() {
System.out.println("Inside testSalutationMessage()");
message = "Hi!" + "Robert";
assertEquals(message,messageUtil.salutationMessage());
}
}

使用 Test Suite 类

  • 创建一个 java 类。
  • 在类中附上 @RunWith(Suite.class) 注释。
  • 使用 @Suite.SuiteClasses 注释给 JUnit 测试类加上引用。
1
2
3
4
5
6
7
8
9
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({
TestJunit1.class,
TestJunit2.class
})
public class JunitTestSuite {
}

创建Test Runner类:

1
2
3
4
5
6
7
8
9
10
11
12
13
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;

public class TestRunner {
public static void main(String[] args) {
Result result = JUnitCore.runClasses(JunitTestSuite.class);
for (Failure failure : result.getFailures()) {
System.out.println(failure.toString());
}
System.out.println(result.wasSuccessful());
}
}

时间测试和异常测试

  • @Test: 测试方法(expected=XXException.class, timeout=xxx)

@Test设置了expected=XXException.class时,这个异常发生后,为测试成功。设置了timeout时,超过时间为测试失败。

参数化测试

Junit 4 引入了一个新的功能参数化测试。参数化测试允许开发人员使用不同的值反复运行同一个测试。你将遵循 5 个步骤来创建参数化测试。

  • 用 @RunWith(Parameterized.class) 来注释 test 类。
  • 创建一个由 @Parameters 注释的公共的静态方法,它返回一个对象的集合(数组)来作为测试数据集合。
  • 创建一个公共的构造函数,它接受和一行测试数据相等同的东西。
    为每一列测试数据创建一个实例变量。
  • 用实例变量作为测试数据的来源来创建你的测试用例。
  • 一旦每一行数据出现测试用例将被调用。让我们看看活动中的参数化测试。
1
2
3
4
5
6
7
8
9
10
public class PrimeNumberChecker {
public Boolean validate(final Integer primeNumber) {
for (int i = 2; i < (primeNumber / 2); i++) {
if (primeNumber % i == 0) {
return false;
}
}
return true;
}
}

创建 Parameterized Test Case 类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import java.util.Arrays;
import java.util.Collection;

import org.junit.Test;
import org.junit.Before;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.junit.runner.RunWith;
import static org.junit.Assert.assertEquals;

@RunWith(Parameterized.class)
public class PrimeNumberCheckerTest {
private Integer inputNumber;
private Boolean expectedResult;
private PrimeNumberChecker primeNumberChecker;

@Before
public void initialize() {
primeNumberChecker = new PrimeNumberChecker();
}

// Each parameter should be placed as an argument here
// Every time runner triggers, it will pass the arguments
// from parameters we defined in primeNumbers() method
public PrimeNumberCheckerTest(Integer inputNumber,
Boolean expectedResult) {
this.inputNumber = inputNumber;
this.expectedResult = expectedResult;
}

@Parameterized.Parameters
public static Collection primeNumbers() {
return Arrays.asList(new Object[][] {
{ 2, true },
{ 6, false },
{ 19, true },
{ 22, false },
{ 23, true }
});
}

// This test will run 4 times since we have 5 parameters defined
@Test
public void testPrimeNumberChecker() {
System.out.println("Parameterized Number is : " + inputNumber);
assertEquals(expectedResult,
primeNumberChecker.validate(inputNumber));
}
}

创建 TestRunner 类

1
2
3
4
5
6
7
8
9
10
11
12
13
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;

public class TestRunner {
public static void main(String[] args) {
Result result = JUnitCore.runClasses(PrimeNumberCheckerTest.class);
for (Failure failure : result.getFailures()) {
System.out.println(failure.toString());
}
System.out.println(result.wasSuccessful());
}
}
1
2
3
4
5
6
Parameterized Number is : 2
Parameterized Number is : 6
Parameterized Number is : 19
Parameterized Number is : 22
Parameterized Number is : 23
true

整合Ant, Maven

参考JUnit.