1. 程式人生 > >JUnit之TestCase和TestSuite詳解

JUnit之TestCase和TestSuite詳解

Android Studio下單元測試的本質其實是根據通過書寫JAVA測試程式碼,通過模擬使用者呼叫相應的方法,或者使用者按下相應的按鍵來驗證我們的程式碼的邏輯是否能達到預期的要求,如果所有的用例都能通過,則證明我們的邏輯滿足要求,否則,可以通過fail()函式(或使用Assert)進行輸出錯誤資訊。 在進行測試前我們首先需要了解一下幾個基本的概念:TestCase,TestSuite:
(圖1) 如圖1所示,TestSuite和TestCase都是繼承自Test介面,同時,TestSuite的建立和使用依賴於TestCase例項,TestCase繼承自Assert類,因此TestCase中可以直接使用Assert中的相關方法,Assert類提供了幾個常用的判斷方法,Assert的類圖可以參照圖2:
(圖2) TestCase: 在進行單元測試的時候,在JUNIT4之前,我們需要測試的程式碼所在的類一般都需要直接或者間接繼承自TestCase,對於我們建立的這個TestCase的子類,我們需要注意在我們這個類的測試流程,假設我們建立的TestCase子類中有兩個測試用例testMethod1和testMethod2,則執行順序可以蠶食圖3所示:

(圖3) 對於我們類中的兩個測試用例testMethod1和testMethod2,都會分別建立一個新的TestCase子類物件,並引起TestCase中的setUp和tearDown函式分別執行一遍,因此,在進行單元測試的過程中,我們可以在setUp當中進行一些初始化操作(如類的某些屬性的賦值操作),在tearDown中進行一些掃尾工作(如類中某些物件所持有資源的釋放)。 一個簡單的Demo:
import junit.framework.TestCase;

public class TestDemo extends TestCase{
	@Override
	protected void setUp() throws Exception {
		// TODO Auto-generated method stub
		super.setUp();
		System.out.println("setUp , hashCode = "+hashCode());
	}
	@Override
	protected void tearDown() throws Exception {
		// TODO Auto-generated method stub
		super.tearDown();
		System.out.println("tearDown,hashCode = "+hashCode());
	}
	public void testMethod1(){
		System.out.println("testMethod1 , hashCode = "+hashCode());
	}
	
	public void testMethod2(){
		System.out.println("testMethod2 , hashCode = "+hashCode());
	}

}



執行結果,如圖4所示:
(圖4) 有兩個test函式,testMethod1和testMethod2,在生命週期的開始函式setUp以及結尾函式tearDown中分別產生了兩次不同的hashCode,根據Java語言中HashCode的概念我們可以知道這分別導致了我們的TestDemo型別的物件建立了兩次。因此如果測試的case增多,我們的TestDemo物件也會建立和case相同的個數。 對於測試用例testMethod1和testMethod2的函式宣告,在我們書寫用例函式的時候需要注意他們有一個共同的特點: 1).訪問許可權都是public; 2).返回型別都是void; 3).沒有引數; 4).方法名以“test”開頭。 在使用單元測試的時候必須注意用例方法的生命格式,否則該用例將不會被執行的到。 TestSuite:
對於suite這個英文單詞,從字面上可以理解為組合或者集合的意思,再加上通過圖1,我們發現TestSuite和TestCase都是實現自Test介面,這很容易讓我們想起JAVA設計模式中的合成模式的概念:即TestSuite可以認為合成模式中的組,是一組TestCase物件的集合;而TestCase物件時這個合成模式中的葉子物件,並且,這些TestCase物件(葉子物件)和TestSuite(組物件)擁有共同的行為(run方法);這樣,可以保證當用戶呼叫組物件TestSuite的run方法的時候,也會呼叫到TestCase物件的run方法。而事實上也確實是這樣,在使用JUnit3執行測試的過程中,會首先建立TestSuite物件,在TestSuite物件的構造方法中,會掃描TestCase子類的所有方法,並呼叫addTestMethod方法,在該方法中呼叫isPublicTestMethod方法判斷是否是待測的方法,若是會呼叫createTest方法,建立一個Test物件,並呼叫addTest方法加入到自己的集合中去,因此執行過程中的TestCase子類都會以具體的test方法個數建立自身例項的個數,並加入到TestSuite中,TestSuite的相對詳細的類圖如圖5所示:
(圖5) 一個簡單的例子瞭解一下TestSuite:
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

public class TestSuiteDemo extends TestSuite{
	public static Test suite(){
		//建立TestSuite物件
		TestSuite suite = new TestSuite();
		//為TestSuite新增一個測試用例集合,引數為:Class<? extends TestCase> testClass
		//通過引數可以知道,其實該引數就是TestCase的子類
		suite.addTestSuite(TestDemo.class);
		//建立具體的測試用例
		Test test = TestSuite.createTest(TestDemo.class, "testMethod1");
		//新增一個具體的測試用例
		suite.addTest(test);
		return suite;
	}
}


執行結果如圖6: (圖6) 通過程式碼和執行結果,我們可以看出testMethod1執行了兩次而testMethod2只執行了一次,通過分析上述程式碼得出testMethod1執行兩次的原因是:第一次是在addTestSuite的時候將其作為一個測試用例傳入到TestSuite中,第二次是通過addTest方法將用例加入到TestSuite中,因此在執行的時候將其執行了兩遍,通過比較hashCode得出總共建立了三個TestCase物件的結論。 通過上述程式碼,我們需要強調一下,如果我們想一次執行一組TestCase實現類的測試,這個時候可以自定義TestSuite物件,將需要測試的TestCase實現類加入到TestSuite中去。我們需要了解TestSuite如何使用,其實TestSuite的使用也很簡單,在TestSuite的使用的時候,我們必須在TestSuite的實現類中,自定義suite方法,由於suite方法會通過反射呼叫,反射呼叫程式碼如下:
public static Test testFromSuiteMethod(Class<?> klass) throws Throwable {
		Method suiteMethod= null;
		Test suite= null;
		try {
			suiteMethod= klass.getMethod("suite");
			if (! Modifier.isStatic(suiteMethod.getModifiers())) {
				throw new Exception(klass.getName() + ".suite() must be static");
			}
			suite= (Test) suiteMethod.invoke(null); // static method
		} catch (InvocationTargetException e) {
			throw e.getCause();
		}
		return suite;
	}

所以suite方法命名規則如下: 1).必須以“suite”方法命名; 2).suite方法的訪問修飾許可權必須為public; 3).suite方法必須為靜態方法; 4).suite方法必須沒有引數。 總結: TestCase和TestSuite類是JUNIT中比較重要的兩個類,TestCase和TestSuite可以認為是JAVA的合成設計模式在單元測試中的應用,其實即便我們沒有自己宣告和建立TestSuite的子類,而且執行的TestCase子類的過程中也會建立TestSuite類,並將要執行的TestCase子類的例項物件新增到TestSuite中去執行,其執行過程可以如圖7所示:
(圖7) 在選擇JUnit執行引擎的時候,便建立了TestSuite物件,並通過上面介紹TestSuite介紹過的addTestMethod,creatTest,addTest方法,將要測的TestCase類中的所有測試用例給掃描出來,並新增到待測列表中去。在執行JUnit測試引擎的run方法時執行TestSuite的的run方法,TestSuite在執行自身run方法時會遍歷所有的TestCase的run方法,同一個TestCase子類的run方法會根據測試用例的個數被執行相應的次數。