zoukankan      html  css  js  c++  java
  • 用JUnit4进行单元测试

    转载:http://tonl.iteye.com/blog/1948869

    参考:

    http://thihy.iteye.com/blog/1771826

    http://developer.51cto.com/art/201103/252490.htm

    http://www.ibm.com/developerworks/cn/java/j-lo-junit4/

    http://www.infoq.com/cn/articles/road-of-automated-unit-testing-practices

    http://coolshell.cn/articles/8209.html

    http://blog.csdn.net/andycpp/article/details/1327147

    http://www.infoq.com/cn/news/2012/02/I-Hate-Unit-Test

    http://coolshell.cn/category/process

    用Junit进行单元测试很方便,尤其是Junit4引入了很多Annotation注解以后。看测试的示例:

    待测试类:

    Java代码  收藏代码
    1. public class Calculator {  
    2.   
    3.     public int add(int a, int b) {  
    4.         return a + b;  
    5.     }  
    6.   
    7.     public int minus(int a, int b) {  
    8.         return a - b;  
    9.     }  
    10.   
    11.     public int square(int n) {  
    12.         return n * n;  
    13.     }  
    14.       
    15.     //Bug : 死循环  
    16.     public void squareRoot(int n) {  
    17.         for(; ;)  
    18.             ;  
    19.     }  
    20.       
    21.     public int multiply(int a, int b) {  
    22.         return a * b;  
    23.     }  
    24.   
    25.     public int divide(int a, int b) throws Exception {  
    26.         if (0 == b) {  
    27.             throw new Exception("除数不能为零");  
    28.         }  
    29.         return a / b;  
    30.     }  
    31. }  

     单元测试类:

    Java代码  收藏代码
    1. import org.junit.After;  
    2. import org.junit.AfterClass;  
    3. import org.junit.Assert;  
    4. import org.junit.Before;  
    5. import org.junit.BeforeClass;  
    6. import org.junit.Ignore;  
    7. import org.junit.Test;  
    8.   
    9. public class CalculatorTest {  
    10.   
    11.     private Calculator cal = new Calculator();  
    12.   
    13.     @BeforeClass // 注意,这里必须是static...因为方法将在类被装载的时候就被调用(那时候还没创建实例)  
    14.     public static void before()  
    15.     {  
    16.         System.out.println("global");  
    17.     }  
    18.   
    19.     @AfterClass  
    20.     public static void after() {  
    21.         System.out.println("global destroy");  
    22.     }  
    23.   
    24.     @Before  
    25.     public void setUp() throws Exception {  
    26.         System.out.println("一个测试开始。。");  
    27.     }  
    28.   
    29.     @After  
    30.     public void tearDown() throws Exception {  
    31.         System.out.println("一个测试结束");  
    32.     }  
    33.   
    34.     @Test  
    35.     @Ignore  
    36.     public void testAdd() {  
    37.         int result = cal.add(1, 2);  
    38.         Assert.assertEquals(3, result);  
    39.     }  
    40.   
    41.     @Test  
    42.     public void testMinus() {  
    43.         int result = cal.minus(5, 2);  
    44.         Assert.assertEquals(3, result);  
    45.     }  
    46.   
    47.     @Test  
    48.     public void testMultiply() {  
    49.         int result = cal.multiply(4, 2);  
    50.         Assert.assertEquals(8, result);  
    51.     }  
    52.   
    53.     @Test(timeout = 1000) // 单位为毫秒  
    54.     public void testSquareRoot() {  
    55.         cal.squareRoot(4);  
    56.     }  
    57.   
    58.     @Test(expected = Exception.class)  
    59.     public void testDivide() throws Exception {  
    60.         System.out.println("teddd");  
    61.         cal.divide(4, 0);// 很简单的办法.......  
    62.     }  
    63.   
    64. //  @Test  
    65. //  public void testDivide() {  
    66. //      int result = 0;  
    67. //      try {  
    68. //          result = cal.divide(10, 5);  
    69. //      } catch (Exception e) {  
    70. //          e.printStackTrace();  
    71. //          Assert.fail();// 如果这行没有执行。说明这部分正确。  
    72. //      }  
    73. //      Assert.assertEquals(2, result);  
    74. //  }  
    75. }  

     在Eclipse里Run As -> JUnit Test,运行测试类,Eclipse的JUnit的View显示如:

            可以看到,CalculatorTest类中总共有5个测试用例,ignore了一个,3个测试用例通过,testSquareRoot测试不通过(因为超时),所以整个的测试结果飘红了。同时,控制台的输出结果为:

    Txt代码  收藏代码
    1. global  
    2. 一个测试开始。。  
    3. 一个测试结束  
    4. 一个测试开始。。  
    5. 一个测试结束  
    6. 一个测试开始。。  
    7. 一个测试结束  
    8. 一个测试开始。。  
    9. teddd  
    10. 一个测试结束  
    11. global destroy  

    各种注解的说明:

    @Test:

    表明该方法是一个测试方法

    @BeforeClass 和 @AfterClass:

    测试用例初始化时执行 @BeforeClass方法,当所有测试执行完毕之后,执行@AfterClass进行收尾工作。标注、@BeforeClass 和 @AfterClass的方法必须是static的,因为方法将在类被装载的时候就被调用,那时候还没创建测试对象实例。

    @Before: 
    使用了该元数据的方法在每个测试方法执行之前都要执行一次。

    @After: 
    使用了该元数据的方法在每个测试方法执行之后要执行一次。

    @Test(expected=*.class) :
    通过@Test元数据中的expected属性验证是否抛出期望的异常,expected属性的值是一个异常的类型,如果抛出了期望的异常,则测试通过,否则不通过。

    @Test(timeout=xxx):
    该元数据传入了一个时间(毫秒)给测试方法,如果测试方法在制定的时间之内没有运行完,则测试也失败。

    @Ignore: 
    该元数据标记的测试方法在测试中会被忽略。同时可以为该标签传递一个String的参数,来表明为什么会忽略这个测试方法。比如:@lgnore("该方法还没有实现"),在执行的时候,仅会报告该方法没有实现,而不会运行测试方法。

    在test方法内除了使用Assert的assertEquals()方法外,还能使用assertFalse()、assertTrue()、assertNull()、assertNotNull()、assertSame()、assertNotSame()等断言函数。而且如果使用的是Junit4,结合Hamcrest,使用

    assertThat([value], [matcher statement])方法可以实现更灵活的断言判断(前提是引入hamcrest的jar包)。

    例如:

    // is匹配符表明如果前面待测的object等于后面给出的object,则测试通过 

    assertThat( testedObj, is( object) ); 

    // containsString匹配符表明如果测试的字符串包含指定的子字符串则测试通过

     assertThat( testedString, containsString( "developerWorks" ) );

    // greaterThan匹配符表明如果所测试的数值testedNumber大于16.0则测试通过

     assertThat( testedNumber, greaterThan(16.0) ); 

    // closeTo匹配符表明如果所测试的浮点型数testedDouble在20.0±0.5范围之内则测试通过 

    assertThat( testedDouble, closeTo( 20.0, 0.5 ) );

    //hasItem匹配符表明被测的迭代对象含有元素element项则测试通过assertThat(iterableObject, hasItem (element));

    更多更详细的Hamcrest提供的断言判断参考:

    http://hi.baidu.com/shenhuanyu09/item/2bcfcb981aa3188e581461b4

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////分割线

           上面的Caculator待测试类里,现在我如果想给square方法多弄几个测试用例,按照上面的方法,我应该写好几个@Test方法来测试,或者每次测完再改一下输入的值和期望得到的值,好麻烦。JUnit提供如下的测试:

    Java代码  收藏代码
    1. import java.util.Arrays;  
    2. import java.util.Collection;  
    3.   
    4. import org.junit.Assert;  
    5. import org.junit.Test;  
    6. import org.junit.runner.RunWith;  
    7. import org.junit.runners.Parameterized;  
    8. import org.junit.runners.Parameterized.Parameters;  
    9.   
    10. @RunWith(Parameterized.class)  
    11. public class CalculatorTest2{  
    12.   
    13.     private Calculator cal = new Calculator();  
    14.     private int param;  
    15.     private int result;  
    16.   
    17.     //构造函数,对变量进行初始化  
    18.     //定义一个待测试的类,并且定义两个变量,一个用于存放参数,一个用于存放期待的结果。  
    19.     public CalculatorTest2(int param, int result) {  
    20.            this.param = param;  
    21.            this.result = result;  
    22.     }  
    23.       
    24.     @Parameters  
    25.     public static Collection data(){  
    26.         return Arrays.asList(new Object[][]{  
    27.             {2, 4},  
    28.             {0, 0},  
    29.             {-3, 9},  
    30.       });  
    31.     }  
    32.   
    33.     @Test  
    34.     public void squareTest() {  
    35.         int temp = cal.square(param);  
    36.         Assert.assertEquals(result, temp);  
    37.     }  
    38. }  

     Eclipse里JUnit的运行结果显示为:

           测试通过了,CalculatorTest2类里的parameter是每次的测试输入,result就是测试的结果。所有的测试输入和期望结果都在@Parameters标注的data函数的返回的Collection集合里,2的期望得到的平方结果值是4,0期望得到0,-3期望得到9。

           把测试代码提交给JUnit框架后,框架如何来运行代码呢?答案就是——Runner。在JUnit中有很多个 Runner,他们负责调用测试代码,每一个Runner都有各自的特殊功能,要根据需要选择不同的Runner来运行测试代码。JUnit中有一个默认Runner,如果没有指定,那么系统自动使用默认 Runner来运行你的代码。这里参数化测试就没有再用默认的Runner了。

    再看看打包测试测例子:

    Java代码  收藏代码
    1. import org.junit.runner.RunWith;  
    2. import org.junit.runners.Suite;  
    3.   
    4. /** 
    5.  * 大家可以看到,这个功能也需要使用一个特殊的Runner, 
    6.  * 因此我们需要向@RunWith标注传递一个参数Suite.class。 
    7.  * 同时,我们还需要另外一个标注@Suite.SuiteClasses, 
    8.  * 来表明这个类是一个打包测试类。我们把需要打包的类作为参数传递给该标注就可以了。 
    9.  * 有了这两个标注之后,就已经完整的表达了所有的含义,因此下面的类已经无关紧要, 
    10.  * 随便起一个类名,内容全部为空既可 
    11.  * 
    12.  */  
    13. @RunWith(Suite.class)  
    14. @Suite.SuiteClasses({ CalculatorTest.class, CalculatorTest2.class })  
    15. public class AllCalculatorTests {  
    16.   
    17. }  

           这个测试类包含了上面的CalculatorTest.class和CalculatorTest2.class里面所有的测试函数,它的目的就是进行打包所有的测试。

    参考:

    http://blog.csdn.net/zhuangxiu/article/details/6256893

    http://blog.csdn.net/songyinan1989/article/details/7445921

    http://www.jb51.net/article/15797.htm

    http://jingbo2759.blog.163.com/blog/static/983753152009711103710146/

  • 相关阅读:
    131. Palindrome Partitioning
    130. Surrounded Regions
    129. Sum Root to Leaf Numbers
    128. Longest Consecutive Sequence
    125. Valid Palindrome
    124. Binary Tree Maximum Path Sum
    122. Best Time to Buy and Sell Stock II
    121. Best Time to Buy and Sell Stock
    120. Triangle
    119. Pascal's Triangle II
  • 原文地址:https://www.cnblogs.com/wenlj/p/4726014.html
Copyright © 2011-2022 走看看