Junit3.8.1代碼閱讀—執(zhí)行流程(textui)[收藏ZZ]
一、 TestRunner.doRun(Test suite,Boolean wait)方法
1、 創(chuàng)建一個(gè)TestResult對(duì)象,該對(duì)象是實(shí)際測(cè)試過(guò)程中的調(diào)度員。他不僅存儲(chǔ)了所有測(cè)試的結(jié)果,調(diào)用中的測(cè)試方法,并將結(jié)果送給ResultPrinter對(duì)象,來(lái)打印結(jié)果。
2、 將生成的ResultPrinter對(duì)象設(shè)置到TestResult對(duì)象中。
3、 取得開始時(shí)間。
4、 調(diào)用Test.run(TestResult)方法。
5、 取得結(jié)束時(shí)間。
6、 打印測(cè)試結(jié)果。
7、 判斷是否需要等待結(jié)束指令,如果需要,等調(diào)用“System.in.read()”等待結(jié)束指令。
二、 Test.run(TestResult)方法—TestCase實(shí)現(xiàn)
Test接口是JUnit框架中最重要的兩個(gè)接口之一,他抽象了所有測(cè)試載體的行為,包括兩個(gè)方法,一個(gè)獲取測(cè)試數(shù)目的countTestCases(),方法,一個(gè)運(yùn)行測(cè)試的run(TestResult)方法。
在JUnit框架中,有兩個(gè)類顯現(xiàn)了這個(gè)接口。一個(gè)是只能容納單個(gè)測(cè)試的TestCase對(duì)象,這里之所以用對(duì)象是因?yàn)樵谖覀冏约簩?shí)現(xiàn)的TestCase子類中可以有多個(gè)測(cè)試方法,但是在JUnit的實(shí)際運(yùn)行中,每個(gè)TestCase對(duì)象只容納一個(gè)測(cè)試方法。
在TestCase的run(TestResult)方法中,會(huì)將實(shí)際的運(yùn)行測(cè)試委派給TestResult的run(TestCase)方法,而 TestResult方法又會(huì)反過(guò)來(lái)調(diào)用TestCase的runBare()方法,將測(cè)試運(yùn)行的結(jié)果放入到對(duì)應(yīng)的Vector中,并通知所有設(shè)定的 TestListener,在這里就是在初始化是設(shè)定的ResultPrinter對(duì)象。
在TestCase的runBare()方法中,實(shí)際上順序調(diào)用初始化setUp()方法,實(shí)行測(cè)試runTest()方法,清除tearDown()方法三個(gè)方法。
TestCase實(shí)現(xiàn)的countTestCases()方法只返回1。
三、 Test.run(TestResult)方法—TestSuite實(shí)現(xiàn)
在JUnit框架中Test接口的另一個(gè)實(shí)現(xiàn)就是TestSuite類,TestSuite類可以說(shuō)是實(shí)現(xiàn)了Test接口的Test的聚集,主要用來(lái)給容 納多個(gè)測(cè)試方法的類。在TestSuite類的內(nèi)部有個(gè)Vector實(shí)例來(lái)容納這個(gè)TestSuite中所有的TestCase對(duì)象。
在 JUnit框架中,對(duì)Test接口的實(shí)現(xiàn)邏輯是一個(gè)比較有意思的東西。特別是TestCase類,他并沒(méi)有像我們想的那樣在run (TestResult)方法中,利用反射調(diào)用子類中每個(gè)以“test”開頭的方法,而是在TestSuite類中解析好方法名以后傳遞給了 TestCase對(duì)象,使得每個(gè)TestCase對(duì)象只能容納一個(gè)測(cè)試方法,并針對(duì)這個(gè)測(cè)試方法調(diào)用初始化setUp()方法和清除tearDown() 方法。
我覺(jué)得這樣并不能達(dá)到“在一個(gè)TestCase中所有測(cè)試方法中公用的變量抽出為類級(jí)的變量,然后在setUp()方法中一起初始 化”。這樣的話我們就沒(méi)有必要在子類中聲明類變量,方正setUp()方法時(shí)針對(duì)每個(gè)測(cè)試方法,我們還不如直接將所有的變量放到測(cè)試方法,省得代碼變得這 里一塊,那里一塊的。真不知道Erich Gamma和Kent Back兩個(gè)高人是咋想的,有明白的希望也能給提個(gè)醒!
還是言歸正題, 話說(shuō)在TestSuite實(shí)現(xiàn)的run(TestResult)方法中,他將所有調(diào)用每個(gè)Vector中每個(gè)Test的run(TestResult)方 法。 TestSuite實(shí)現(xiàn)的countTestCases()方法返回包含的Test的個(gè)數(shù)。
四、 TestListener接口
JUnit框架中有兩個(gè)重要的接口,一個(gè)是上面介紹的Test接口,下面就介紹另一個(gè)重要的接口—TestListener接口。
Test 接口抽象了所有測(cè)試載體的行為,而TestListener接口抽象了所有測(cè)試監(jiān)聽者的行為,他包括兩個(gè)添加錯(cuò)誤和失敗的方法:addError (Test,Throwable)和addFailure(Test,AssertionFailedError)方法,開始測(cè)試startTest (Test)方法,結(jié)束測(cè)試endTest(Test)方法。
在JUnit框架中有兩個(gè)類實(shí)現(xiàn)了這個(gè)接口,一個(gè)負(fù)責(zé)結(jié)果打印的ResultPrinter類,一個(gè)是所有TestRunner的基礎(chǔ)類BaseTestRunner類。
五、 ResultPrinter類
ResultPrinter類負(fù)責(zé)所有測(cè)試結(jié)果的打印,他有兩個(gè)類變量,一個(gè)是fColumn負(fù)責(zé)紀(jì)錄測(cè)試的數(shù)目,當(dāng)?shù)剿氖畟€(gè)時(shí)換行,在從零計(jì)數(shù)。Fwriter是一個(gè)PrintSteam對(duì)象負(fù)責(zé)結(jié)果的打印。
ResultPrinter實(shí)現(xiàn)的startTest(Test)中,完成測(cè)試數(shù)目的統(tǒng)計(jì)和換行,并打印出我們熟悉的”.”。 ResultPrinter實(shí)現(xiàn)的addError()方法和addFailure()方法只是打印出對(duì)應(yīng)“E”和“F”。
ResultPrinter實(shí)現(xiàn)的ednTest(Test)中,什么也沒(méi)有做。
ResultPrinter 類中另一個(gè)重要的方法是print(TestResult,runTime)方法,他包括四個(gè)部分printHeader(runTime)打印所用時(shí) 間,printErrors(TestResult)打印所有錯(cuò)誤,printFailures(TestResult)打印所有失敗, printFooter(TestResult)打印結(jié)果,也就是“OK (100 test)”。
這里在啰嗦幾句JUnit框架中的Error和Failure,Error是在我們的測(cè)試方法中報(bào)出來(lái)的異常,而Failure是我們使用assertXX()方法,判斷失敗而報(bào)出的異常。
六、 TestRunner類
BaseTestRunner 類中,將TestListener接口的四個(gè)方法都委派給子類實(shí)現(xiàn),而在TestRunner類中,這些方法中又什么都沒(méi)有做,我想可能是當(dāng)初想用 TestRunner來(lái)實(shí)現(xiàn)測(cè)試結(jié)果打印,可是后來(lái)發(fā)現(xiàn)應(yīng)該用一個(gè)單獨(dú)的類來(lái)處理所有在TestRunner類中就沒(méi)有實(shí)現(xiàn)這些方法。不過(guò)我想 TestRuner類中實(shí)現(xiàn)TestListener接口還是有一點(diǎn)用處的,比如想在一個(gè)類中集成多個(gè)TestRunner。
七、 Assert類
最后說(shuō)說(shuō)測(cè)試方法中必須的assertXX()方法,所有這些方法都放在一個(gè)叫Assert的類中,因?yàn)樗械臏y(cè)試方法的執(zhí)行都在TestCase類中, 所以TestCase類繼承了Assert類。 Assert類也沒(méi)有什么好說(shuō)的就是一堆a(bǔ)ssertXX()方法。
八、 TestResult類
TestResult 類中用兩個(gè)Vector來(lái)記錄測(cè)試的結(jié)果fErrors和fFailues。用一個(gè)Vector來(lái)存放所有的TestListener。一個(gè)整數(shù)存放測(cè)試 的數(shù)目,一個(gè)布爾變量存放停止標(biāo)志。總覺(jué)得TestResult類的實(shí)現(xiàn)有點(diǎn)別扭,感覺(jué)上他應(yīng)該是一個(gè)存放測(cè)試結(jié)果的類,可是JUnit的實(shí)現(xiàn)中總覺(jué)得有 點(diǎn)像控制器,由他調(diào)用TestCase中的測(cè)試方法總覺(jué)得別扭。
九、 系統(tǒng)結(jié)構(gòu)總結(jié)
看JUnit框架有兩個(gè)感覺(jué),第一個(gè)“小”;第二個(gè)“實(shí)用”。可能平時(shí)自己在工作中也實(shí)現(xiàn)過(guò)類似的功能,可是并沒(méi)有仔細(xì)想個(gè)它的通用性,以及從整個(gè)框架上的結(jié)構(gòu)上系統(tǒng)的考慮。Erich Gamma和Kent Back兩個(gè)高人---高人真高!
Test 接口的抽象和實(shí)現(xiàn)典型的合成模式的應(yīng)用,間接自然。輕描淡寫一個(gè)清晰的樹結(jié)構(gòu)就出來(lái)了。 TestListener接口總覺(jué)得有點(diǎn)別扭。可能單獨(dú)的抽象出TestResult接口更好看。要是在多一個(gè)控制器接口,可能整個(gè)框架看起來(lái)更好看。要 求怎么怎么多,其實(shí)我覺(jué)得這樣完全實(shí)現(xiàn)了功能并且提供了很好的擴(kuò)展性,可是畢竟是高人寫的,所以我們的要求當(dāng)然要高點(diǎn)。
1、 創(chuàng)建一個(gè)TestResult對(duì)象,該對(duì)象是實(shí)際測(cè)試過(guò)程中的調(diào)度員。他不僅存儲(chǔ)了所有測(cè)試的結(jié)果,調(diào)用中的測(cè)試方法,并將結(jié)果送給ResultPrinter對(duì)象,來(lái)打印結(jié)果。
2、 將生成的ResultPrinter對(duì)象設(shè)置到TestResult對(duì)象中。
3、 取得開始時(shí)間。
4、 調(diào)用Test.run(TestResult)方法。
5、 取得結(jié)束時(shí)間。
6、 打印測(cè)試結(jié)果。
7、 判斷是否需要等待結(jié)束指令,如果需要,等調(diào)用“System.in.read()”等待結(jié)束指令。
二、 Test.run(TestResult)方法—TestCase實(shí)現(xiàn)
Test接口是JUnit框架中最重要的兩個(gè)接口之一,他抽象了所有測(cè)試載體的行為,包括兩個(gè)方法,一個(gè)獲取測(cè)試數(shù)目的countTestCases(),方法,一個(gè)運(yùn)行測(cè)試的run(TestResult)方法。
在JUnit框架中,有兩個(gè)類顯現(xiàn)了這個(gè)接口。一個(gè)是只能容納單個(gè)測(cè)試的TestCase對(duì)象,這里之所以用對(duì)象是因?yàn)樵谖覀冏约簩?shí)現(xiàn)的TestCase子類中可以有多個(gè)測(cè)試方法,但是在JUnit的實(shí)際運(yùn)行中,每個(gè)TestCase對(duì)象只容納一個(gè)測(cè)試方法。
在TestCase的run(TestResult)方法中,會(huì)將實(shí)際的運(yùn)行測(cè)試委派給TestResult的run(TestCase)方法,而 TestResult方法又會(huì)反過(guò)來(lái)調(diào)用TestCase的runBare()方法,將測(cè)試運(yùn)行的結(jié)果放入到對(duì)應(yīng)的Vector中,并通知所有設(shè)定的 TestListener,在這里就是在初始化是設(shè)定的ResultPrinter對(duì)象。
在TestCase的runBare()方法中,實(shí)際上順序調(diào)用初始化setUp()方法,實(shí)行測(cè)試runTest()方法,清除tearDown()方法三個(gè)方法。
TestCase實(shí)現(xiàn)的countTestCases()方法只返回1。
三、 Test.run(TestResult)方法—TestSuite實(shí)現(xiàn)
在JUnit框架中Test接口的另一個(gè)實(shí)現(xiàn)就是TestSuite類,TestSuite類可以說(shuō)是實(shí)現(xiàn)了Test接口的Test的聚集,主要用來(lái)給容 納多個(gè)測(cè)試方法的類。在TestSuite類的內(nèi)部有個(gè)Vector實(shí)例來(lái)容納這個(gè)TestSuite中所有的TestCase對(duì)象。
在 JUnit框架中,對(duì)Test接口的實(shí)現(xiàn)邏輯是一個(gè)比較有意思的東西。特別是TestCase類,他并沒(méi)有像我們想的那樣在run (TestResult)方法中,利用反射調(diào)用子類中每個(gè)以“test”開頭的方法,而是在TestSuite類中解析好方法名以后傳遞給了 TestCase對(duì)象,使得每個(gè)TestCase對(duì)象只能容納一個(gè)測(cè)試方法,并針對(duì)這個(gè)測(cè)試方法調(diào)用初始化setUp()方法和清除tearDown() 方法。
我覺(jué)得這樣并不能達(dá)到“在一個(gè)TestCase中所有測(cè)試方法中公用的變量抽出為類級(jí)的變量,然后在setUp()方法中一起初始 化”。這樣的話我們就沒(méi)有必要在子類中聲明類變量,方正setUp()方法時(shí)針對(duì)每個(gè)測(cè)試方法,我們還不如直接將所有的變量放到測(cè)試方法,省得代碼變得這 里一塊,那里一塊的。真不知道Erich Gamma和Kent Back兩個(gè)高人是咋想的,有明白的希望也能給提個(gè)醒!
還是言歸正題, 話說(shuō)在TestSuite實(shí)現(xiàn)的run(TestResult)方法中,他將所有調(diào)用每個(gè)Vector中每個(gè)Test的run(TestResult)方 法。 TestSuite實(shí)現(xiàn)的countTestCases()方法返回包含的Test的個(gè)數(shù)。
四、 TestListener接口
JUnit框架中有兩個(gè)重要的接口,一個(gè)是上面介紹的Test接口,下面就介紹另一個(gè)重要的接口—TestListener接口。
Test 接口抽象了所有測(cè)試載體的行為,而TestListener接口抽象了所有測(cè)試監(jiān)聽者的行為,他包括兩個(gè)添加錯(cuò)誤和失敗的方法:addError (Test,Throwable)和addFailure(Test,AssertionFailedError)方法,開始測(cè)試startTest (Test)方法,結(jié)束測(cè)試endTest(Test)方法。
在JUnit框架中有兩個(gè)類實(shí)現(xiàn)了這個(gè)接口,一個(gè)負(fù)責(zé)結(jié)果打印的ResultPrinter類,一個(gè)是所有TestRunner的基礎(chǔ)類BaseTestRunner類。
五、 ResultPrinter類
ResultPrinter類負(fù)責(zé)所有測(cè)試結(jié)果的打印,他有兩個(gè)類變量,一個(gè)是fColumn負(fù)責(zé)紀(jì)錄測(cè)試的數(shù)目,當(dāng)?shù)剿氖畟€(gè)時(shí)換行,在從零計(jì)數(shù)。Fwriter是一個(gè)PrintSteam對(duì)象負(fù)責(zé)結(jié)果的打印。
ResultPrinter實(shí)現(xiàn)的startTest(Test)中,完成測(cè)試數(shù)目的統(tǒng)計(jì)和換行,并打印出我們熟悉的”.”。 ResultPrinter實(shí)現(xiàn)的addError()方法和addFailure()方法只是打印出對(duì)應(yīng)“E”和“F”。
ResultPrinter實(shí)現(xiàn)的ednTest(Test)中,什么也沒(méi)有做。
ResultPrinter 類中另一個(gè)重要的方法是print(TestResult,runTime)方法,他包括四個(gè)部分printHeader(runTime)打印所用時(shí) 間,printErrors(TestResult)打印所有錯(cuò)誤,printFailures(TestResult)打印所有失敗, printFooter(TestResult)打印結(jié)果,也就是“OK (100 test)”。
這里在啰嗦幾句JUnit框架中的Error和Failure,Error是在我們的測(cè)試方法中報(bào)出來(lái)的異常,而Failure是我們使用assertXX()方法,判斷失敗而報(bào)出的異常。
六、 TestRunner類
BaseTestRunner 類中,將TestListener接口的四個(gè)方法都委派給子類實(shí)現(xiàn),而在TestRunner類中,這些方法中又什么都沒(méi)有做,我想可能是當(dāng)初想用 TestRunner來(lái)實(shí)現(xiàn)測(cè)試結(jié)果打印,可是后來(lái)發(fā)現(xiàn)應(yīng)該用一個(gè)單獨(dú)的類來(lái)處理所有在TestRunner類中就沒(méi)有實(shí)現(xiàn)這些方法。不過(guò)我想 TestRuner類中實(shí)現(xiàn)TestListener接口還是有一點(diǎn)用處的,比如想在一個(gè)類中集成多個(gè)TestRunner。
七、 Assert類
最后說(shuō)說(shuō)測(cè)試方法中必須的assertXX()方法,所有這些方法都放在一個(gè)叫Assert的類中,因?yàn)樗械臏y(cè)試方法的執(zhí)行都在TestCase類中, 所以TestCase類繼承了Assert類。 Assert類也沒(méi)有什么好說(shuō)的就是一堆a(bǔ)ssertXX()方法。
八、 TestResult類
TestResult 類中用兩個(gè)Vector來(lái)記錄測(cè)試的結(jié)果fErrors和fFailues。用一個(gè)Vector來(lái)存放所有的TestListener。一個(gè)整數(shù)存放測(cè)試 的數(shù)目,一個(gè)布爾變量存放停止標(biāo)志。總覺(jué)得TestResult類的實(shí)現(xiàn)有點(diǎn)別扭,感覺(jué)上他應(yīng)該是一個(gè)存放測(cè)試結(jié)果的類,可是JUnit的實(shí)現(xiàn)中總覺(jué)得有 點(diǎn)像控制器,由他調(diào)用TestCase中的測(cè)試方法總覺(jué)得別扭。
九、 系統(tǒng)結(jié)構(gòu)總結(jié)
看JUnit框架有兩個(gè)感覺(jué),第一個(gè)“小”;第二個(gè)“實(shí)用”。可能平時(shí)自己在工作中也實(shí)現(xiàn)過(guò)類似的功能,可是并沒(méi)有仔細(xì)想個(gè)它的通用性,以及從整個(gè)框架上的結(jié)構(gòu)上系統(tǒng)的考慮。Erich Gamma和Kent Back兩個(gè)高人---高人真高!
Test 接口的抽象和實(shí)現(xiàn)典型的合成模式的應(yīng)用,間接自然。輕描淡寫一個(gè)清晰的樹結(jié)構(gòu)就出來(lái)了。 TestListener接口總覺(jué)得有點(diǎn)別扭。可能單獨(dú)的抽象出TestResult接口更好看。要是在多一個(gè)控制器接口,可能整個(gè)框架看起來(lái)更好看。要 求怎么怎么多,其實(shí)我覺(jué)得這樣完全實(shí)現(xiàn)了功能并且提供了很好的擴(kuò)展性,可是畢竟是高人寫的,所以我們的要求當(dāng)然要高點(diǎn)。
posted on 2007-07-12 13:13 想飛就飛 閱讀(719) 評(píng)論(0) 編輯 收藏 所屬分類: J2EE