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/

  • 相关阅读:
    0xx_nodeJS
    0xx_jQuery
    0xx_正则表达式
    0xx_ES6
    centos重启关机命令
    tomcat服务开机启动脚本
    mysql授权总结
    centos创建文件命令
    svn如果无法连接有可能导致右键卡
    简单导出excel
  • 原文地址:https://www.cnblogs.com/wenlj/p/4726014.html
Copyright © 2011-2022 走看看