步驟(測試代碼中含有“suite”):
1. Main方法先new TestResult,然后待用start方法;start方法中主要做了兩件事情,初始化解析加載測試集,即getTest;另外一件是執(zhí)行調(diào)度測試集并記錄測試結(jié)果,即doRun
2. 在start方法中調(diào)用BaseTestRunner中的getTest(),在getTest中,通過反射檢查測試代碼中是否含有“suite”關(guān)鍵字,如果有則按有“suite”模式執(zhí)行,上面已經(jīng)說明過來
3. 如果沒有則,創(chuàng)建一個(gè)測試TestSuite
new TestSuite(testClass)
4. 將一個(gè)個(gè)testSuite對象加載到測試集中
5. 通過反射的方法,從測試代碼中解析出所有測試方法,然后篩選出test開頭,且參數(shù)為空,類型為viod的方法,找到待測試的方法(6中篩選過濾),然后通過反射后newInstance一個(gè)個(gè)測試方法,轉(zhuǎn)化成Junit的測試用例(testcase)
6. 將Junit轉(zhuǎn)化的測試用例加載fTest測試集中,待執(zhí)行
另外:注意一點(diǎn),當(dāng)測試代碼中含有構(gòu)造函數(shù),時(shí),在上圖中第5步中,會判斷是否含有構(gòu)造函數(shù),如果有增加兩步,則按照下圖所示執(zhí)行,
(1) 通過反射找到構(gòu)造函數(shù),
(2) 通過構(gòu)造函數(shù)初始化構(gòu)造對象,即tecase
1.2 運(yùn)行調(diào)度階段
Junit在執(zhí)行調(diào)度測試代碼過程中比較簡單,主要有兩種情況,一種情況按照正常的情況調(diào)用,另外一種情況,如果代碼中需要重復(fù)執(zhí)行某個(gè)測試方法時(shí),則需要調(diào)度repeateTest類
下圖先簡單說明下正常情況
其步驟如下:
1. 在3.1中初始化解析完成測試對象后,需要調(diào)度執(zhí)行測試測試代碼,在start方法中調(diào)用doRun方法
2. 創(chuàng)建一個(gè)測試結(jié)果集TestResult,初始化TestResult中的主要參數(shù)fFailures、fErrors、fListener、fRunTests、fStop
3. TestResult調(diào)用TestSuite中的run方法,并且循環(huán)找出結(jié)果集中的所有測試對象,即Juint中的testcase
4. TestSuite調(diào)用testRun方法
5. testRun方法調(diào)用TestCase中的run方法
6. run中調(diào)用了runProtected方法,并通過內(nèi)部類實(shí)現(xiàn)對protect()
7. 通過protect()調(diào)用runBare()方法
8. 從第九步以后調(diào)用了測試函數(shù),完成了整個(gè)執(zhí)行過程(不包括執(zhí)行結(jié)果捕捉和記錄)
兩外,對于測試代碼中含有“RepeatedTest”關(guān)鍵字的,執(zhí)行流程稍有不同,如下圖,其過程不一一解釋,可以結(jié)合上面的解釋了解下。
suite.addTest(new RepeatedTest(new CalculatorTest("testSubtract"), 3));
1.3 運(yùn)行結(jié)果捕捉及記錄階段
執(zhí)行結(jié)果捕捉和記錄是測試過程非常重要的一部分,所以把這部分過程單獨(dú)拿出來說明下,前幾部分都非常簡單,
第四步是通過反射調(diào)用測試方法,測試方法再通過調(diào)用被測代碼,然后產(chǎn)生預(yù)期結(jié)果,
第五步是通過斷言方法,實(shí)現(xiàn)對實(shí)際執(zhí)行結(jié)果和預(yù)期結(jié)果比對,
第六步如果預(yù)期結(jié)果與實(shí)際結(jié)果不相同則調(diào)用failNotEquals
第八步如果錯(cuò)誤,調(diào)用fail方法,實(shí)現(xiàn)返回throw new AssertionFailedError(message),異常
后面幾步通過異常捕捉捕捉錯(cuò)誤,通過TestResult類中的addFailure進(jìn)行處理實(shí)現(xiàn)。在這塊Junit通過觀察者模式實(shí)現(xiàn)對測試結(jié)果的動(dòng)態(tài)捕捉和記錄(關(guān)于觀察者模式后面繼續(xù)討論)。具體過程詳見下圖
關(guān)于錯(cuò)誤的捕捉(Error)的實(shí)現(xiàn)和Fail的比較像,在這不?嗦了。
兩外,在這說明下,JUnit中的兩個(gè)概念錯(cuò)誤(error)與失。╢ailure)
1) 錯(cuò)誤指的是代碼中拋出了異常等影響代碼正常執(zhí)行的情況,比如拋出了ArrayIndexOutOfBoundsException,這叫做錯(cuò)誤。
2) 失敗指的是我們斷言所期待的結(jié)果與程序?qū)嶋H執(zhí)行的結(jié)果不一致,或者是直接調(diào)用了fail()方法,這叫做失敗。