Java 單元測試利器之 Junit


       前言:

          因為工作和學習的需要,在代碼中查錯的時候,第一步就是想知道這個錯誤具體發生在一個位置,進行一個准確的定位。而這個定位的工作交給誰來做了呢?不難猜出也就是這篇博客的主題---Junit。junit是一個開源的框架,也是java這一塊的測試工具之一。想了解詳細請上官網,下面用代碼來跟大家解釋。

         准備要測試的方法,放進一個類中方便於測試。

View Code
package com.junit3_8;

/**
 * junt3.8單元測試
 * 
 * @author CHH
 * @since 2013-01-19
 * 
 */
public class Calculator {

    //
    public int add(int a, int b) {
        
        int sum=0;
        for(int i=0;i<100;i++){
            sum +=i;
            
        }
        System.out.println("加=="+sum);
        return a+b;
    }

    //
    public int subtract(int a, int b) {
        int sum=0;
        for(int i=0;i<100;i++){
            sum +=i;
            
        }
        System.out.println("減=="+sum);
        return a - b;
    }

    //
    public int multiply(int a, int b) {
        int sum=0;
        for(int i=0;i<100;i++){
            sum +=i;
            
        }
        System.out.println("乘==="+sum);
        return a * b;
    }

    //
    public int divide(int a, int b) throws Exception {
        int sum=0;
        for(int i=0;i<100;i++){
            sum +=i;
            
        }
        System.out.println("除==="+sum);
        
        if (0 == b) {
            throw new Exception("除數不能為0");
        }
        return a / b;
    }
}

        Junit3.8測試類

View Code
package com.junit3_8;

import junit.framework.Assert;
import junit.framework.TestCase;
/**
 * 
 * @author CHH
 * @since 2013-01-19
 */
public class CalculatorTest extends TestCase {
    
    Calculator cal;
    
    //在“每個”測試方法執行之前被調用  
    public void setUp()  
    {  
        //這段代碼在這寫比較方便,只寫一次就夠,  
        //不用在每個方法里寫,因為這個方法每次都被調用,生成不同的對象,供測試方法使用  
        cal = new Calculator();  
    }
    
    //在“每個”測試方法執行之后被調用  
    public void tearDown()  
    {  
         
    }
    
    //測試方法:方法名要以test為開頭,無參數,無返回類型  
    public void testAdd()  
    {  
        //Calculator cal = new Calculator();  
        int result = cal.add(1, 2); 
        //第一個參數是預期的,第二個參數是真實的  
        
        Assert.assertEquals(3, result); 
        
        //Assert.fail();
          
    } 
    
    public void testSubtract()  
    {  
        //Calculator cal = new Calculator();  
        int result = cal.subtract(1, 2);  
        //第一個參數是預期的,第二個參數是真實的  
        Assert.assertEquals(-1, result);  
          
    }
    
    public void testMultiply()  
    {  
        //Calculator cal = new Calculator();  
        int result = cal.multiply(1, 2);  
        //第一個參數是預期的,第二個參數是真實的  
        Assert.assertEquals(2, result);  
          
    }
    
    public void testDivide()  
    {  
        int result = 0;  
        //Calculator cal = new Calculator();  
        try   
        {  
            result = cal.divide(4, 2);  
              
        }  
        catch(Exception e)  
        {  
            e.printStackTrace();  
            //讓測試失敗  
            Assert.fail();  
        }  
        //第一個參數是預期的,第二個參數是真實的  
        Assert.assertEquals(2, result);  
          
    }
    
    //除數為0的情況  
    public void testDivideByZero()  
    {  
        Throwable th = null ;  
          
        //Calculator cal = new Calculator();  
        try   
        {  
            cal.divide(1, 0);  
            Assert.fail();  
        }  
        catch(Exception e)  
        {  
            th = e ;  
            //e.printStackTrace();  
        }  
          
        //th 不為空 null  
        Assert.assertNotNull(th);  
        //第一個參數是預期的,第二個參數是真實的  
        Assert.assertEquals(Exception.class, th.getClass());  
        Assert.assertEquals("除數不能為0", th.getMessage());  
          
    }
    
    //加了這個main方法,可以直接以 Java Application 方式運行 ,也可以以 JUnit Test 運行  
    public static void main(String[] args)  
    {  
        //命令行形式打印  
        junit.textui.TestRunner.run(CalculatorTest.class);  
          
        //awt 界面方式顯示  
        //junit.awtui.TestRunner.run(CalculatorTest.class);  
          
        //swing 界面方式顯示  
        //junit.swingui.TestRunner.run(CalculatorTest.class);  
    }

}

 

     從上面的代碼中可以看出Junit測試類是通過繼承一個TestCase類來實現方法的測試,而這就是Junit4.0以前的測試方式,而在4.0之后他們的實現方式又有了稍微的變化。

Junit4.0之后不再是通過繼承TestCase的方式來實現方法的實測,而是采用注解的方式進行的。根據Java 5.0中的新特征(注解,靜態導入等),Junit開發團隊也隨之靠攏,采用注解的方式來進行方法的測試。這樣下來相比而言JUnit 4更簡單、更豐富和更易於使用。

        Junit4.0測試類

View Code
package com.junit4_0;

import static org.junit.Assert.assertEquals;

import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
/**
 * Junit4.0
 * @author CHH
 * @since 2013-01-19 晚上10:12
 *
 */
public class CalculatorTest {

    private static Calculator calculator = new Calculator();

    //每個方法測試前調用
    @Before
    public void clearCalculator() {
        calculator.clear();
    }
    
    //每個方法測試完以后調用
    @After 
    public void tearDown()  
    {  
         
    }
    
    //@Test:測試方法,表明這是一個測試方法。在Junit中將會自動被執行。
    @Test
    public void add() {
        calculator.add(1);
        calculator.add(1);
        //第一個參數是預期的,第二個參數是真實的  
        assertEquals(calculator.getResult(), 2);
    }

    @Test
    public void subtract() {
        calculator.add(10);
        calculator.substract(2);
        //第一個參數是預期的,第二個參數是真實的  
        assertEquals(calculator.getResult(), 8);
    }

    //給測試函數設定一個執行時間,超過了這個時間(400毫秒),它們就會被系統強行終止
    @Test(timeout=400)
    public void divide() {
        calculator.add(8);
        calculator.divide(2);
        //第一個參數是預期的,第二個參數是真實的  
        assert calculator.getResult() == 5;
    }

    //使用注釋來聲明該異常是預期的,異常測試是Junit4中的最大改進
    @Test(expected = ArithmeticException.class)
    public void divideByZero() {
        calculator.divide(0);
    }

    //@Ignore:忽略的測試方法,標注的含義就是“某些方法尚未完成,暫不參與此次測試”
    @Ignore("not ready yet")
    @Test
    public void multiply() {
        calculator.add(10);
        calculator.multiply(10);
        //第一個參數是預期的,第二個參數是真實的  
        assertEquals(calculator.getResult(), 100);
    }

}

 

  Junit4出了采用的注解的方式來進行測試方法之外,還增加了一些新的元素。

     A、JUnit4添加了兩個比較數組的assert() 方法:

  public static void assertEquals(Object[] expected, Object[] actual)

  public static void assertEquals(String message, Object[] expected, Object[] actual)

 

  Junit4常用注解:

    @Test  測試方法,表明這是一個測試方法。在Junit中將會自動被執行。

    @Test(timeOut=400)  給測試函數設定一個執行時間,超過了這個時間(400毫秒),它們就會被系統強行終止

    @Test(expected = ArithmeticException.class)  使用注釋來聲明該異常是預期的,異常測試是Junit4中的最大改進

    @Ignore("not ready yet")    忽略的測試方法,標注的含義就是“某些方法尚未完成,暫不參與此次測試”

    @Before   每個方法測試前調用

    @After   每個方法測試完以后調用

    @BeforeClass   每個類運行前調用,並且只調用一次

    @AfterClass  每個類運行后調用,並且只調用一次

  

  表格.@BeforeClass/@AfterClass比較於@Before/@After。

@BeforeClass和@AfterClass @Before和@After
在每個類中只有一個方法能被注解。 多個方法能被注解,但其執行的順序未特別指定,且不運行重載方法。
方法名是不相關的 方法名是不相關的
每個類運行一次 在每個測試方法運行前或運行后運行
在當前類的@BeforeClass方法運行前先運行超類的@BeforeClass方法。在超類中聲明的@AfterClass方法將在所有當前類的該方法運行后才運行。 超類中的@Before在所有子類的該方法運行前運行。在超類中的@After在在所有子類的該方法運行后才運行。
必須是公共和非靜態的。 必須是公共和非靜態的。
即使一個@BeforeClass方法拋出一個異常,所有的@AfterClass方法也保證被運行。 即使一個@Before或者@Test方法拋出一個異常,所有的@After方法也保證被運行。

 

  總結:這兩個版本最大的區別在JUnit3.x中測試必須繼承 TestCase,並且每個方法名必須以test開頭。比如:testMethod1()而在JUnit4.x中不必繼承TestCase,采用了注解的 方式。只要在測試的方法上加上注解@Test即可,從而不必再遵循以前的一些顯式約定和反射定位測試;在JUnit4.x中如果繼承了TestCase, 注解就不起作用了。並且有很重要的一點就是在JUnit4.x中繼承了TestCase后,在OutLine視圖中測試單個方法時,結果整個類都run 了。還有一點就是,在3.x中需要實現setUp和tearDown方法,而在4.x中無需這樣,可以自定義需要在測試前和測試后的方法,在方法前加上 @before,@after就可以了。所以在JUnit4.x不必繼承TestCase用注解即可對單個方法進行測試。

 

 

  

 

         

       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM