JUnit3.8的Junit單元測試.

悠悠隱於市發表於2011-01-26
注:轉自JavaEye中zhouwendong006的部落格http://zhouwendong006.iteye.com/blog/372795

1.  建立一個工程,取名隨意。

2.  建立包(com.test.junit3),並建立一個計算類(Calculator),新增其相應的方法。完成後程式碼如下:

Java程式碼 
public class Calculator {    
   
    public int add(int a, int b) {    
        return a + b;    
    }    
   
    public int minus(int a, int b) {    
        return a - b;    
    }    
   
    public int multiply(int a, int b) {    
        return a * b;    
    }    
   
    public int divide(int a, int b) throws Exception {    
        if (0 == b) {    
            throw new Exception("除數不能為0!");    
        }    
        return a / b;    
    }    
}   
public class Calculator {

	public int add(int a, int b) {
		return a + b;
	}

	public int minus(int a, int b) {
		return a - b;
	}

	public int multiply(int a, int b) {
		return a * b;
	}

	public int divide(int a, int b) throws Exception {
		if (0 == b) {
			throw new Exception("除數不能為0!");
		}
		return a / b;
	}
}這裡面的方法比較簡單,不在解釋。

3.  建立測試類。

     a.  建立測試類的時候(我指的是使用Eclipse或者MyEclipse進行開發的時候),一般將測試類放到另外一個原始檔夾中。在專案上點右鍵,選擇new-->Source Folder。名字隨意,一般取名字test。

     b.  建立測試包。包名一般與需要被測試的類的包名相同,在這裡,包名與Calculator類的包名相同(com.test.junit3)。

     c.   建立測試類。測試類命名一般是需要被測試的類名加上字尾“Test”,這裡為CalculatorTest。

4.  測試類需要注意的方面。在這裡,也就是CalculatorTest需要遵守的規則。

     a.  測試類必須繼承TestCase類。

     b.  測試方法必須為public型的,void的,沒有方法引數,且方法名必須以“test”為字首,即以test開頭(如果不以test開頭,那該方法需要手動啟動測試。執行測試類的時候,該方法是無法被自動進行測試的)。

5. 實際的測試類。

Java程式碼 
package com.test.junit3;    
   
import junit.framework.Assert;    
import junit.framework.TestCase;    
   
public class CalculatorTest extends TestCase{    
   
    private Calculator cal;    
        
    /**   
     * 執行每一個測試方法的時候,先執行setUp();   
     */   
    protected void setUp() throws Exception {    
        cal=new Calculator();           
    }    
   
    /**   
     * 執行每一個測試方法之後,執行tearDown();   
     */   
    protected void tearDown() throws Exception {    
        super.tearDown();    
    }    
        
    public void testAdd(){    
        int result=cal.add(1, 2);    
        //斷言:assert    
        Assert.assertEquals(3, result);    
    }    
        
    public void testMinus(){    
        int result =cal.minus(1, 2);    
        Assert.assertEquals(-1, result);    
    }    
        
    public void testMultiply(){    
        int result =cal.multiply(2, 3);    
        Assert.assertEquals(6, result);    
    }    
        
    public void testDivied(){    
        int result=0;    
        try {    
            result = cal.divide(6, 4);    
        } catch (Exception e) {    
            e.printStackTrace();    
            Assert.fail();    
        }    
        Assert.assertEquals(1, result);    
    }    
        
    public void testDivied2(){    
        Throwable tx=null;    
        try {    
            cal.divide(4, 0);    
            Assert.fail();    
        } catch (Exception e) {    
            tx=e;    
        }    
                
        //斷言tx是否為空    
        Assert.assertNotNull(tx);    
            
        //斷言兩個物件是否相同    
        Assert.assertEquals(Exception.class,tx.getClass());    
            
        //斷言String是否相同    
        Assert.assertEquals("除數不能為0!", tx.getMessage());    
    }    
}   
package com.test.junit3;

import junit.framework.Assert;
import junit.framework.TestCase;

public class CalculatorTest extends TestCase{

	private Calculator cal;
	
	/**
	 * 執行每一個測試方法的時候,先執行setUp();
	 */
	protected void setUp() throws Exception {
		cal=new Calculator();		
	}

	/**
	 * 執行每一個測試方法之後,執行tearDown();
	 */
	protected void tearDown() throws Exception {
		super.tearDown();
	}
	
	public void testAdd(){
		int result=cal.add(1, 2);
		//斷言:assert
		Assert.assertEquals(3, result);
	}
	
	public void testMinus(){
		int result =cal.minus(1, 2);
		Assert.assertEquals(-1, result);
	}
	
	public void testMultiply(){
		int result =cal.multiply(2, 3);
		Assert.assertEquals(6, result);
	}
	
	public void testDivied(){
		int result=0;
		try {
			result = cal.divide(6, 4);
		} catch (Exception e) {
			e.printStackTrace();
			Assert.fail();
		}
		Assert.assertEquals(1, result);
	}
	
	public void testDivied2(){
		Throwable tx=null;
		try {
			cal.divide(4, 0);
			Assert.fail();
		} catch (Exception e) {
			tx=e;
		}
			
		//斷言tx是否為空
		Assert.assertNotNull(tx);
		
		//斷言兩個物件是否相同
		Assert.assertEquals(Exception.class,tx.getClass());
		
		//斷言String是否相同
		Assert.assertEquals("除數不能為0!", tx.getMessage());
	}
}
   a.  如果被測試的方法絕對不會有異常丟擲(如:Calculator中的add(int a,int b)),那麼在測試類(CalculatorTest)中可以像下面的程式碼一樣,直接使用斷言Assert類中的assertEquals(int expected, int actual)方法直接斷言。該方法傳入兩個int引數,一個表示期望值,即按照設計應該得到的結果expected,一個表示實際值,即程式實際得到的結果actual。如果這兩個結果相同,則表示被測試的類即(Calculator)中的該方法沒有錯誤。

Java程式碼 
public void testAdd(){    
    int result=cal.add(1, 2);    
    //斷言:assert    
    Assert.assertEquals(3, result);    
}   
	public void testAdd(){
		int result=cal.add(1, 2);
		//斷言:assert
		Assert.assertEquals(3, result);
	}       補充:Assert中的assertEquals()方法傳入的引數基本可以是所有的型別,包括String、int、char等等,具體的自己看。注意:預期值和實際值的型別必須一致。

    b.  如果被測試的方法有異常丟擲(如:Calculator中的divied(int a,int b)),那麼在測試類中如果直接使用斷言Assert中的assertEquals(int expected, int actual)方法時,傳入引數b為0的時候,如下:

Java程式碼 
public void testDivied(){    
    int result=0;    
    try {    
        result = cal.divide(6, 0);    
    } catch (Exception e) {    
        e.printStackTrace();    
        Assert.fail();    
    }    
    Assert.assertEquals(1, result);    
}   
	public void testDivied(){
		int result=0;
		try {
			result = cal.divide(6, 0);
		} catch (Exception e) {
			e.printStackTrace();
			Assert.fail();
		}
		Assert.assertEquals(1, result);
	}       無論你的程式碼是否完善,是否已經正確無誤了,TestBar顯示仍為紅條,表示該方法無法通過測試。正確的寫法應該如下:

Java程式碼 
public void testDivied2(){    
   
    //Throwable為Exception和Error的父類.    
    Throwable tx=null;    
    try {    
        cal.divide(4, 0);    
        Assert.fail();    
    } catch (Exception e) {    
        tx=e;    
    }    
        
    //斷言tx是否為空    
    Assert.assertNotNull(tx);    
        
    //斷言兩個物件是否相同    
    Assert.assertEquals(Exception.class,tx.getClass());    
        
    //斷言異常資訊是否為指定異常資訊。tx.getMessage()獲取異常丟擲的資訊    
    Assert.assertEquals("除數不能為0!", tx.getMessage());    
}   
	public void testDivied2(){

		//Throwable為Exception和Error的父類.
		Throwable tx=null;
		try {
			cal.divide(4, 0);
			Assert.fail();
		} catch (Exception e) {
			tx=e;
		}
		
		//斷言tx是否為空
		Assert.assertNotNull(tx);
		
		//斷言兩個物件是否相同
		Assert.assertEquals(Exception.class,tx.getClass());
		
		//斷言異常資訊是否為指定異常資訊。tx.getMessage()獲取異常丟擲的資訊
		Assert.assertEquals("除數不能為0!", tx.getMessage());
	}       “Assert.fail;”表示該方法測試失敗,它的目的是:假如它被執行到了,那麼表示divide(int a,int b)方法沒有丟擲異常,也就是方法中有bug。

       “tx=e;”將異常e賦給tx,將區域性變數賦給全域性變數,以便進行下面操作。

       “Assert.assertNotNull(tx);”斷言tx是否為空,如果tx為空,則說明divide(int a,int b)方法沒有將異常丟擲,方法中存在bug。

       “Assert.assertEquals(Exception.class,tx.getClass());”。tx.getClass()可以得到tx,也就是這個異常是哪個類,然後斷言是否與你期望的異常類相同。如果不同,測試失敗,方法丟擲異常錯誤,方法中存在bug。其實到這裡可以結束了,而“Assert.assertEquals("除數不能為0!",tx.getMessage());”是為了通過斷言異常資訊,更進一步判斷該異常是否是你在方法中指定的異常。

       這樣,通過這些斷言,可以保證你的方法目前沒有發現bug存在,測試的時候,該方法會通過,表現方式為TestBar為綠色通過。

6.  在測試的時候,再TestCase中有兩個方法,一個為setUp(),表示初始化。該方法在每個測試方法執行之前將被首先執行。比如如果要執行testAdd()方法的時候,先要執行一遍setUp()方法。因此該方法一般進行一些初始化操作,比如對被測試類的例項化,如:

Java程式碼 
protected void setUp() throws Exception {    
    cal=new Calculator();       
}   
	protected void setUp() throws Exception {
		cal=new Calculator();	
	}  

       另一個方法為tearDown(),該方法在每個測試方法執行之後執行,因此該方法一般處理每個測試方法結束後的資源釋放操作。

       總的來說:如果測試類中有3個測試方法test1(),test2(),test3(),那麼方法的執行順序為

       setUp()->test1()->tearDown()->setUp()->test2()->tearDown()->setUp()->test3()->tearDown()

7.  測試的時候,一般要注意臨界值的測試。如除數不能為0,索引越界等問題。

8.  如果在沒有IDE的情況下,可以通過使用TestRunner類進行測試,如以下程式碼所示

Java程式碼 
public static void main(String[] args) {    
    junit.awtui.TestRunner.run(CalculatorTest.class);    
}   
	public static void main(String[] args) {
		junit.awtui.TestRunner.run(CalculatorTest.class);
	}       需要注意的是:在junit.awtui、junit.swingui和junit.textui三個包下均有TestRunner類,任何一個類都可以執行測試任務。只是表現的方式不同,看你喜歡用哪個了!

9.  在執行多個測試類的時候,一個一個點執行,進行測試顯然是非常費時的事情。junit提供了一個類TestSuite可以將多個測試類一起執行,進行測試。示例程式碼如下:

Java程式碼 
package com.test.junit3;    
   
import junit.framework.Test;    
import junit.framework.TestCase;    
import junit.framework.TestSuite;    
   
public class TestAll extends TestCase {    
        
    /**   
     * 該方法名稱必須為suite(),不能更改   
     * 該方法中   
     * TestSuite物件不僅可以新增測試類,還可以包裝suite物件   
     * @return   
     */   
    public static Test suite(){    
            
        TestSuite suite=new TestSuite();    
        suite.addTestSuite(LargestTest.class);    
        suite.addTestSuite(CalculatorTest.class);    
            
        return suite;    
    }    
}   
package com.test.junit3;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

public class TestAll extends TestCase {
	
	/**
	 * 該方法名稱必須為suite(),不能更改
	 * 該方法中
	 * TestSuite物件不僅可以新增測試類,還可以包裝suite物件
	 * @return
	 */
	public static Test suite(){
		
		TestSuite suite=new TestSuite();
		suite.addTestSuite(LargestTest.class);
		suite.addTestSuite(CalculatorTest.class);
		
		return suite;
	}
}
  

       如註釋所示,該靜態方法名稱必須為suite(),原因可以參看junit原始碼。另外該方法返回Test物件。TestSuite中有兩個方法很重要,一個是addTestSuite(),可以直接新增測試類。另一個方法為addTest(),可以新增TestSuite物件,所以,上面也可以通過下面的程式碼實現:

Java程式碼 
package com.test.junit3;    
   
import junit.framework.Test;    
import junit.framework.TestCase;    
import junit.framework.TestSuite;    
   
public class TestAll extends TestCase {    
        
    public static Test suite(){    
            
        TestSuite suite=new TestSuite();    
            
        TestSuite suite1=new TestSuite();    
        suite1.addTestSuite(LargestTest.class);    
            
        TestSuite suite2=new TestSuite();    
        suite2.addTestSuite(CalculatorTest.class);    
            
        suite.addTest(suite1);    
        suite.addTest(suite2);    
   
        return suite;    
    }    
}   
package com.test.junit3;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

public class TestAll extends TestCase {
	
	public static Test suite(){
		
		TestSuite suite=new TestSuite();
		
		TestSuite suite1=new TestSuite();
		suite1.addTestSuite(LargestTest.class);
		
		TestSuite suite2=new TestSuite();
		suite2.addTestSuite(CalculatorTest.class);
		
		suite.addTest(suite1);
		suite.addTest(suite2);

		return suite;
	}
}
       這樣我們可以方便的對多個測試類進行測試了。

 

相關文章