JUnit110413: JUnit快速入门注记Email: zcatt@163.com
Blog http://zcatt.blog.chinaunix.net
内容提要通过一个实例快速入门JUnit4.以供备忘和参考。
声明仅限学习交流,禁止商业用途。转载需注明出处。
版本记录Date Ver Note
2011-04-13 0.1 Draft. zcatt, Beijing
JUnit4中广泛的使用了annotation(注记), 简化了test的编写. 下面首先以一个例子介绍JUnit的使用, 随后汇总JUnit中一些主要的annotation. 本文的例子主要取材于[2], 致谢.
环境的配置=======================
这里以Windows cmdline为例介绍. IDE中,尤其是eclipse中的junit使用很是便利,无需赘述.
下载junit, 放到一个目录中, 并设定CLASSPATH.
本例,
- d:\JavaLib\junit-4.8.2.jar
设置环境变量
- CLASSPATH=.;d:\JavaLib\junit-4.8.2.jar
编译源码=======================
javac编译,
本例, 两个源码文件calculator.java和calculatorTest.java, 假设位于E:\Test.
- E:\Test>javac calculator.java calculatorTest.java
测试=======================
执行测试,
- java org.junit.runner.JUnitCore
本例,
- E:\Test>java org.junit.runner.JUnitCore calculatorTest
-
JUnit version 4.8.2
-
..EI..E
-
Time: 1.031
-
There were 2 failures:
-
1) testSubstract(calculatorTest)
-
java.lang.AssertionError: expected:<8> but was:<9>
-
at org.junit.Assert.fail(Assert.java:91)
-
at org.junit.Assert.failNotEquals(Assert.java:645)
-
at org.junit.Assert.assertEquals(Assert.java:126)
-
at org.junit.Assert.assertEquals(Assert.java:470)
-
at org.junit.Assert.assertEquals(Assert.java:454)
-
at calculatorTest.testSubstract(calculatorTest.java:30)
-
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
-
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
-
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
-
at java.lang.reflect.Method.invoke(Method.java:597)
-
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
-
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
-
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
-
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
-
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
-
at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
-
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
-
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
-
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
-
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
-
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
-
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
-
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
-
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
-
at org.junit.runners.Suite.runChild(Suite.java:128)
-
at org.junit.runners.Suite.runChild(Suite.java:24)
-
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
-
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
-
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
-
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
-
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
-
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
-
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
-
at org.junit.runner.JUnitCore.run(JUnitCore.java:136)
-
at org.junit.runner.JUnitCore.run(JUnitCore.java:117)
-
at org.junit.runner.JUnitCore.runMain(JUnitCore.java:98)
-
at org.junit.runner.JUnitCore.runMainAndExit(JUnitCore.java:53)
-
at org.junit.runner.JUnitCore.main(JUnitCore.java:45)
-
2) testSquareRoot(calculatorTest)
-
java.lang.Exception: test timed out after 1000 milliseconds
-
at calculator.squareRoot(calculator.java:19)
-
at calculatorTest.testSquareRoot(calculatorTest.java:47)
-
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
-
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
-
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
-
at java.lang.reflect.Method.invoke(Method.java:597)
-
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
-
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
-
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
-
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
-
at org.junit.internal.runners.statements.FailOnTimeout$1.run(FailOnTimeout.java:28)
-
-
FAILURES!!!
-
Tests run: 4, Failures: 2
-
-
E:\Test>
测试结果中, E代表error, I代表ignore.
本例源码文件
- //calculator.java
-
public class calculator {
-
private static int result; // 静态变量,用于存储运行结果
-
public void add(int n) {
-
result = result + n;
-
}
-
public void substract(int n) {
-
result = result - 1; //Bug: 正确的应该是 result =result-n
-
}
-
public void multiply(int n) {
-
} // 此方法尚未写好
-
public void divide(int n) {
-
result = result / n;
-
}
-
public void square(int n) {
-
result = n * n;
-
}
-
public void squareRoot(int n) {
-
for (; ;) ; //Bug : 死循环
-
}
-
public void clear() { // 将结果清零
-
result = 0;
-
}
-
public int getResult() {
-
return result;
-
}
-
}
- //calculatorTest.java
-
import static org.junit.Assert.*;
-
-
import org.junit.Before;
-
import org.junit.Test;
-
import org.junit.Ignore;
-
-
-
public class calculatorTest {
-
-
private static calculator cal = new calculator();
-
-
@Before
-
public void setUp() throws Exception {
-
cal.clear();
-
}
-
-
@Test
-
public void testAdd() {
-
cal.add(2);
-
cal.add(3);
-
assertEquals(5, cal.getResult());
-
-
}
-
-
@Test
-
public void testSubstract() {
-
cal.add(10);
-
cal.substract(2);
-
assertEquals(8, cal.getResult());
-
}
-
-
@Ignore("Multiply() Not yet implemented")
-
@Test
-
public void testMultiply() {
-
}
-
-
@Test
-
public void testDivide() {
-
cal.add(8);
-
cal.divide(2);
-
assertEquals(4, cal.getResult());
-
}
-
-
@Test(timeout=1000)
-
public void testSquareRoot() {
-
cal.squareRoot(4);
-
assertEquals(2, cal.getResult());
-
}
-
-
}
JUnit4中的annotation=======================
JUnit4使用annotation来发现要测试的方法.而以前的JUnit版本使用前缀test的signature辨别方式发现测试方法.
罗列一些常用的annotation:
@Test, 是测试方法
@Test(timeout=num_ms), 若超时, 则认为error
@Ignore, 忽略这个测试方法
@Before, 类似以前的setUp(), 是每个测试方法执行前都要运行的fixture. 可以修饰多个方法, 但多个方法间执行的次序不定.
@After, 类似以前的tearDown(), 是每个测试方法执行后都要运行的fixture. 可以修饰多个方法, 但多个方法间执行的次序不定.
@BeforeClass, 是每个测试类执行前都要运行的fixture, 仅执行一次. 只可修饰一个public static方法.
@AfterClass, 是每个测试类执行后都要运行的fixture, 仅执行一次. 只可修饰一个public static方法.
@RunWith(TestClassRunner.class), 修饰test class, 指定runner. 如不指定RunWith, 则默认runner是org.junit.internal.runners.TestClassRunner.
@Parameters, 需要输入多组数据反复测试时, 可以使用@Parameters, 预先定义好这些数据, JUnit的org.junit.runners.Parameterized这个runner会自动喂给测试. @Parameters用于修饰返回这些预定义数据的public static方法, 而且这个方法必须返回Collection借口. 细节见后面的列子.
- package junit4;
-
-
import calc.Calculator;
-
import static org.junit.Assert.assertEquals;
-
import org.junit.Test;
-
import org.junit.runner.RunWith;
-
import org.junit.runners.Parameterized;
-
import org.junit.runners.Parameterized.Parameters;
-
-
import java.util.Arrays;
-
import java.util.Collection;
-
-
@RunWith(Parameterized.class
-
public class SquareTest {
-
-
private static Calculator calculator = new Calculator();
-
private int param;
-
private int result;
-
-
@Parameters
-
public static Collection data() {
-
return Arrays.asList(new Object[][]{
-
{0, 0},
-
{1, 1},
-
{2, 4},
-
{4, 16}, // OK : 4 = 16
-
{5, 25},
-
{6, 36},
-
{7, 48} // NOK : 7 = 49 not 48
-
});
-
}
-
-
public SquareTest(int param, int result) {
-
this.param = param;
-
this.result = result;
-
}
-
-
@Test
-
public void square() {
-
calculator.square(param);
-
assertEquals(result, calculator.getResult());
-
}
-
-
}
@Suite, 用于组合多个测试.
- package junit4;
-
-
import org.junit.runner.RunWith;
-
import org.junit.runners.Suite;
-
-
@RunWith(Suite.class)
-
@Suite.SuiteClasses({
-
CalculatorTest.class,
-
SquareTest.class
-
})
-
public class AllCalculatorTests {
-
}
参考
1.
2.
Get Acquainted with the New Advanced Features of JUnit 4
阅读(852) | 评论(0) | 转发(0) |