Junit 內部解密之: Test + TestCase + TestSuite
Interface: Test 整個測試的的基礎接口
Method 1: abstract int countTestCases() 這個方法主要是用來計算要運行的test case的數量的。
Method 2:abstract void run(TestResult result) 這個方法主要是用來執行一個測試用例并且在測試結果的實例中收集它的測試結果。
Class:TestCase
定義:abstract class TestCase extends Assert implements Test 繼承了Assert類并且實現了Test接口。而且是個抽象類。
Class: TestSuite
定義:class TestSuite implements Test; Test接口的實現類,和TestCase一樣. 但是TestSuite是一系列testcase的集合,將所有要運行的testcase add到TestSuite。
觀察一:TestCase 和 TestSuite類都實現了Test 接口。
好處一:由于當你給TestSuite增加一個對象時,實際上增加的是Test,而不只是個TestCase,這樣我們既可以在TestSuite里面增加另一個TestSuite,也可以加入一個TestCase。如果是TestCase,那么會運行那個單獨的測試;如果是TestSuite,那么運行一組測試。
如何實現:那么是如何實現上面說的那個好處呢?看下TestSuite的一個addtest方法明白了:
Public void addTest(Test test) 新增一個test到testsuite,直接使用fTests.add(test)來新增。
這里可以新增的入參是Test接口,而不是一個TestCase對象,所以只要實現了Test接口的實現類,包括TestCase和TestSuite,都可以不斷的增加下去。這樣引出了好處二和設計模式。
好處二:當我們為自己的應用程序創建特殊的suite或組合出TestAll類非常容易。簡單說明下TestAll類:僅僅包含了一個靜態的suite方法,會注冊需要定期執行的所有的Test對象(包括TestCase對象和TestSuite對象)。
Java設計模式:Composite模式
定義:把對象組合(composite)成樹狀結構來表示部分-整體層次關系,Composite模式可以讓客戶一致的對待單個對象和對象的組合。
我們來看下Junit的Test接口和TestCase和TestSuite類是如何實現Composite模式的:
先搞清楚Junit里面的部分-整體分別是什么,這里單個的TestCase可以看作是部分,把復合的TestCase(TestSuite)看作是整體,看下面的圖:
我們可以看到這樣的模式會帶來另外一些好處:
簡化了JUnit的代碼 JUnit可以統一處理組合結構TestSuite和單個對象TestCase。使JUnit開發變得簡單容易,因為不需要區分部分和整體的區別,不需要寫一些充斥著if else的選擇語句。
好處三:TestCase是個抽象實現類,而且繼承了Assert類,這里為啥要繼承Assert類呢?因為在一個testcase中是肯定需要用的Assert斷言的,如果不繼承Assert類,那么testcase方法中要寫成Assert.assert(),不是很簡潔,現在繼承了Assert類后,我們可以在繼承了TestCase類的測試類中直接assert(),使測試代碼看得非常簡潔和清楚。
定義了TestCase對象和TestSuite的類層次結構 基本對象TestCase可以被組合成更復雜的組合對象TestSuite,而這些組合對象又可以被組合,如我們上個例子,這樣不斷地遞歸下去。客戶代碼中,任何使用基本對象的地方都方便的使用組合對象,大大簡化系統維護和開發。
仔細看看Test接口的方法,它存在一個是countTestCases方法,它來統計這次測試有多少個TestCase,另外一個方法run。還有一個參數TestResult,它來統計測試結果。這里為啥存在一個run方法呢? 我們想想Junit在run testcase的時候,需要把這些testcase的組成打包后成為請求發送到Junit Framework,這樣我們實現TestCase類的時候,可以自由的實現run方法去打包發送請求。這樣我們在寫測試用例時候,只需繼承TestCase,來完成run方法即可,把測試結果記錄到TestResult中,這樣的做法好引出另外的Java設計模式。
Java設計模式:Command模式
定義:將一個請求封裝成一個對象,從而使你可用不同的請求對客戶進行參數化;對請求進行排隊或記錄請求日志...,Command告訴我們可以為一個操作生成一個對象并給出它的一個execute(執行)方法。
run()是我們的Command模式的Excecute方法:
我們可以看到這樣的模式會帶來另外一些好處:
Command模式將實現請求的一方(TestCase開發)和調用一方(JUnit Fromwork)分離開。
Command模式可以將多個TestCase進行組合成一個復合命令,實際你將看到TestSuit是它的復合命令。