Chinaunix首页 | 论坛 | 博客
  • 博客访问: 173622
  • 博文数量: 47
  • 博客积分: 992
  • 博客等级: 准尉
  • 技术积分: 565
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-08 21:57
文章分类

全部博文(47)

文章存档

2019年(1)

2018年(1)

2017年(1)

2014年(6)

2013年(1)

2012年(2)

2011年(35)

我的朋友

分类: Java

2011-04-13 14:18:07

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.

本例,
  1. d:\JavaLib\junit-4.8.2.jar


设置环境变量
  1. CLASSPATH=.;d:\JavaLib\junit-4.8.2.jar





编译源码
=======================

javac编译,
  1. javac


本例, 两个源码文件calculator.java和calculatorTest.java, 假设位于E:\Test.

  1. E:\Test>javac calculator.java calculatorTest.java





测试
=======================

执行测试,

  1. java org.junit.runner.JUnitCore


本例,
  1. E:\Test>java org.junit.runner.JUnitCore calculatorTest
  2. JUnit version 4.8.2
  3. ..EI..E
  4. Time: 1.031
  5. There were 2 failures:
  6. 1) testSubstract(calculatorTest)
  7. java.lang.AssertionError: expected:<8> but was:<9>
  8. at org.junit.Assert.fail(Assert.java:91)
  9. at org.junit.Assert.failNotEquals(Assert.java:645)
  10. at org.junit.Assert.assertEquals(Assert.java:126)
  11. at org.junit.Assert.assertEquals(Assert.java:470)
  12. at org.junit.Assert.assertEquals(Assert.java:454)
  13. at calculatorTest.testSubstract(calculatorTest.java:30)
  14. at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  15. at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
  16. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
  17. at java.lang.reflect.Method.invoke(Method.java:597)
  18. at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
  19. at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
  20. at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
  21. at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
  22. at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
  23. at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
  24. at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
  25. at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
  26. at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
  27. at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
  28. at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
  29. at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
  30. at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
  31. at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
  32. at org.junit.runners.Suite.runChild(Suite.java:128)
  33. at org.junit.runners.Suite.runChild(Suite.java:24)
  34. at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
  35. at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
  36. at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
  37. at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
  38. at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
  39. at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
  40. at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
  41. at org.junit.runner.JUnitCore.run(JUnitCore.java:136)
  42. at org.junit.runner.JUnitCore.run(JUnitCore.java:117)
  43. at org.junit.runner.JUnitCore.runMain(JUnitCore.java:98)
  44. at org.junit.runner.JUnitCore.runMainAndExit(JUnitCore.java:53)
  45. at org.junit.runner.JUnitCore.main(JUnitCore.java:45)
  46. 2) testSquareRoot(calculatorTest)
  47. java.lang.Exception: test timed out after 1000 milliseconds
  48. at calculator.squareRoot(calculator.java:19)
  49. at calculatorTest.testSquareRoot(calculatorTest.java:47)
  50. at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  51. at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
  52. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
  53. at java.lang.reflect.Method.invoke(Method.java:597)
  54. at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
  55. at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
  56. at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
  57. at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
  58. at org.junit.internal.runners.statements.FailOnTimeout$1.run(FailOnTimeout.java:28)

  59. FAILURES!!!
  60. Tests run: 4, Failures: 2

  61. E:\Test>

测试结果中, E代表error, I代表ignore.

本例源码文件

  1. //calculator.java
  2. public class calculator {
  3.     private static int result; // 静态变量,用于存储运行结果
  4.     public void add(int n) {
  5.         result = result + n;
  6.     }
  7.     public void substract(int n) {
  8.         result = result - 1; //Bug: 正确的应该是 result =result-n
  9.     }
  10.     public void multiply(int n) {
  11.     } // 此方法尚未写好
  12.     public void divide(int n) {
  13.         result = result / n;
  14.     }
  15.     public void square(int n) {
  16.         result = n * n;
  17.     }
  18.     public void squareRoot(int n) {
  19.         for (; ;) ; //Bug : 死循环
  20.     }
  21.     public void clear() { // 将结果清零
  22.         result = 0;
  23.     }
  24.     public int getResult() {
  25.         return result;
  26.     }
  27. }


  1. //calculatorTest.java
  2. import static org.junit.Assert.*;

  3. import org.junit.Before;
  4. import org.junit.Test;
  5. import org.junit.Ignore;


  6. public class calculatorTest {

  7.     private static calculator cal = new calculator();
  8.     
  9.     @Before
  10.     public void setUp() throws Exception {
  11.         cal.clear();
  12.     }

  13.     @Test
  14.     public void testAdd() {
  15.         cal.add(2);
  16.         cal.add(3);
  17.         assertEquals(5, cal.getResult());
  18.         
  19.     }

  20.     @Test
  21.     public void testSubstract() {
  22.            cal.add(10);
  23.            cal.substract(2);
  24.            assertEquals(8, cal.getResult());
  25.      }

  26.     @Ignore("Multiply() Not yet implemented")
  27.     @Test
  28.     public void testMultiply() {
  29.     }

  30.     @Test
  31.     public void testDivide() {
  32.         cal.add(8);
  33.         cal.divide(2);
  34.         assertEquals(4, cal.getResult());
  35.     }

  36.     @Test(timeout=1000)
  37.     public void testSquareRoot() {
  38.         cal.squareRoot(4);
  39.         assertEquals(2, cal.getResult());
  40.     }
  41.     
  42. }

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借口. 细节见后面的列子.


  1. package junit4;

  2. import calc.Calculator;
  3. import static org.junit.Assert.assertEquals;
  4. import org.junit.Test;
  5. import org.junit.runner.RunWith;
  6. import org.junit.runners.Parameterized;
  7. import org.junit.runners.Parameterized.Parameters;

  8. import java.util.Arrays;
  9. import java.util.Collection;

  10. @RunWith(Parameterized.class
  11. public class SquareTest {

  12.     private static Calculator calculator = new Calculator();
  13.     private int param;
  14.     private int result;

  15.     @Parameters
  16.     public static Collection data() {
  17.         return Arrays.asList(new Object[][]{
  18.                 {0, 0},
  19.                 {1, 1},
  20.                 {2, 4},
  21.                 {4, 16}, // OK : 4 = 16
  22.                 {5, 25},
  23.                 {6, 36},
  24.                 {7, 48} // NOK : 7 = 49 not 48
  25.         });
  26.     }

  27.     public SquareTest(int param, int result) {
  28.         this.param = param;
  29.         this.result = result;
  30.     }

  31.     @Test
  32.     public void square() {
  33.         calculator.square(param);
  34.         assertEquals(result, calculator.getResult());
  35.     }

  36. }

@Suite, 用于组合多个测试.

  1. package junit4;

  2. import org.junit.runner.RunWith;
  3. import org.junit.runners.Suite;

  4. @RunWith(Suite.class)
  5. @Suite.SuiteClasses({
  6.         CalculatorTest.class,
  7.         SquareTest.class
  8.         })
  9. public class AllCalculatorTests {
  10. }


参考

1.
2. Get Acquainted with the New Advanced Features of JUnit 4
阅读(818) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~