下圖是根據(jù)源代碼分析出來(lái)的framework包中各個(gè)關(guān)鍵類之間的關(guān)系
Assert類提供了JUnit使用的一整套的斷言,這套斷言都被TestCase繼承下來(lái),Assert也變成了透明的。
Test接口是為了統(tǒng)一TestCase和TestSuite的類型;
TestCase里面提供了運(yùn)行單元測(cè)試類的方法;
TestSuite中則提供了加載單元測(cè)試類,檢驗(yàn)測(cè)試類格式等等的方法。
TestResult故名思意是提供存放測(cè)試結(jié)果的地方,但是在JUnit中它還帶有一點(diǎn)控制器的功能。
TestListener接口抽象了所有測(cè)試監(jiān)聽(tīng)者的行為,他包括添加錯(cuò)誤和失敗的方法,開(kāi)始測(cè)試和結(jié)束測(cè)試的方法。在JUnit框架中有兩個(gè)類實(shí)現(xiàn)了這個(gè)接口,一個(gè)負(fù)責(zé)結(jié)果打印的ResultPrinter類,一個(gè)是所有TestRunner的基礎(chǔ)類BaseTestRunner類(這兩個(gè)類都不在framework包中)。
1.2 extentions包中類設(shè)計(jì)分析
在上面我們已經(jīng)提到了junit.extentions包中的內(nèi)容TestSetup。來(lái)看看整個(gè)包的結(jié)構(gòu)吧。
先簡(jiǎn)要的介紹下包中各個(gè)類的功能。
ActiveTestSuite對(duì)TestSuite進(jìn)行了改進(jìn),使得每個(gè)test運(yùn)行在一個(gè)單獨(dú)的線程里面,并且只到所有的線程都結(jié)束了才會(huì)結(jié)束整個(gè)測(cè)試。
ExceptionTestCase是對(duì)TestCase進(jìn)行的改進(jìn),可以方便的判斷測(cè)試類是否拋出了期望的異常。
剩下的三個(gè)類,使用了裝飾模式來(lái)設(shè)計(jì)的。其中TestDecorator為具體裝飾類制定好了使用規(guī)則,RepeatedTest和TestSetup則是具體實(shí)現(xiàn)的裝飾類。
那為什么extentions包中ActiveTestSuite和ExceptionTestCase沒(méi)有使用裝飾模式呢?原因在于裝飾模式在結(jié)構(gòu)上要求存在類似于組合模式的遞歸。而對(duì)于已有的TestCase和TestSuite來(lái)說(shuō),直接繼承它們要比構(gòu)建一個(gè)新的遞歸結(jié)構(gòu)要來(lái)得快得多而且簡(jiǎn)單;并且這些增強(qiáng)功能都只是針對(duì)TestCase或者TestSuite。使用了裝飾模式來(lái)擴(kuò)展的類與以上不同的是,它們功能的增強(qiáng)是針對(duì)任何Test實(shí)現(xiàn)的。如果不采用裝飾模式同樣的功能要為T(mén)estCase、TestSuite以及以后的其他Test實(shí)現(xiàn)分別寫(xiě)出子類。因此使用裝飾模式能夠很巧妙的解決這個(gè)問(wèn)題。
1.3 runner包中類設(shè)計(jì)分析
在junit.runner包。重要的是BaseTestRunner這個(gè)類,所有運(yùn)行入口或者圖形界面都是集成了這個(gè)類,剩下其他的類使用反射機(jī)制來(lái)將測(cè)試類加載進(jìn)來(lái),還有讀取properties文件的操作。當(dāng)然這部分也非常重要,如果想學(xué)習(xí)下反射機(jī)制的應(yīng)用以及嘗試寫(xiě)自己的類加載器可以閱讀這部分的源碼(關(guān)于反射技術(shù)后續(xù)會(huì)繼續(xù)分析)。
剩下的三個(gè)包這里也不作介紹,大部分的內(nèi)容都是GUI的繪制(當(dāng)然junit.textui包除外)。
這樣,對(duì)JUnit的整體框架有了全面的認(rèn)識(shí)?傮w來(lái)說(shuō)各個(gè)包分工明確,設(shè)計(jì)上采用了必要的設(shè)計(jì)模式來(lái)增強(qiáng)了擴(kuò)展性和重用性(其設(shè)計(jì)模式后續(xù)繼續(xù)分析),很值得學(xué)習(xí)和借鑒。
JUNIT源碼探秘(三):JUNIT整體執(zhí)行過(guò)程分析
在閱讀Junit源碼時(shí),需要對(duì)Junit執(zhí)行測(cè)試代碼的整體過(guò)程比較了解,這樣才能夠更好的學(xué)習(xí)Junit。所以本節(jié)主要介紹下Junit的執(zhí)行過(guò)程
在執(zhí)行過(guò)程中使用Java Application,在執(zhí)行過(guò)程中加載運(yùn)行參數(shù):
-version, 3, -port, 10115, -testLoaderClass, org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestLoader, -loaderpluginname, org.eclipse.jdt.junit.runtime, -classNames, com.wonew.junit.TestAll
當(dāng)運(yùn)行一個(gè)測(cè)試代碼時(shí),先new一個(gè)TestRunner對(duì)象,同時(shí)給每一個(gè)TestRunner創(chuàng)建一個(gè)TestResult對(duì)象
根據(jù)代碼可以看出JUnit 的完整執(zhí)行過(guò)程分為兩步:初始化加載用例集階段(getTest)、運(yùn)行調(diào)度和結(jié)果捕捉階段(doRun),為了方便說(shuō)嗎我們把這兩部分分解成三個(gè)階段:即初始化加載用例集階段、運(yùn)行調(diào)度和結(jié)果捕捉記錄階段