隨著軟件項目的逐漸增大,軟件測試在軟件開發(fā)中的地位顯得越來越重要。如果軟件項目沒有良好的測試流程,隨著系統(tǒng)的增大,無論項目管理人員還是軟件開發(fā)人員都會對項目的前景失去信心,甚至?xí)䦟椖康哪繕?biāo)產(chǎn)生分歧,因為長期以來沒有對程序代碼和系統(tǒng)設(shè)計進行有效的控制,很多問題都被暫時掩蓋或逐漸演化成其他的問題。軟件開發(fā)周期越長,會使得問題進化的版本越多,后造成的結(jié)果是“剪不斷,理還亂”。
單元測試是整個測試流程中基礎(chǔ)的部分,它們要求程序員盡可能早地發(fā)現(xiàn)問題,并給予控制,這是其一。另外,如果集成測試出現(xiàn)問題,它們可以幫助診斷。這樣為在軟件開發(fā)流程中建立高效的事件反應(yīng)機制打下了堅實基礎(chǔ)。
JUnit是為Java程序開發(fā)者實現(xiàn)單元測試提供一種框架,使得Java單元測試更規(guī)范有效,并且更有利于測試的集成。
JUnit的內(nèi)部結(jié)構(gòu)
JUnit的軟件結(jié)構(gòu)
JUnit 共有七個包,核心的包是junit.framework 和junit.runner。Framework包負責(zé)整個測試對象的構(gòu)架,Runner負責(zé)測試驅(qū)動。
JUnit的類結(jié)構(gòu)
JUnit有四個重要的類:TestSuite、TestCase、TestResult、TestRunner。前三個類屬于Framework包,后一個類在不同的環(huán)境下是不同的。這里使用的是文本測試環(huán)境,所以用的是 junit.textui.TestRunner。各個類的職責(zé)如下:
1.TestResult,負責(zé)收集TestCase所執(zhí)行的結(jié)果,它將結(jié)果分為兩類,客戶可預(yù)測的Failure和沒有預(yù)測的Error。同時負責(zé)將測試結(jié)果轉(zhuǎn)發(fā)到TestListener(該接口由TestRunner繼承)處理;
2.TestRunner,客戶對象調(diào)用的起點,負責(zé)對整個測試流程的跟蹤。能夠顯示返回的測試結(jié)果,并且報告測試的進度。
3.TestSuite, 負責(zé)包裝和運行所有的TestCase。
4.TestCase, 客戶測試類所要繼承的類,負責(zé)測試時對客戶類進行初始化,以及測試方法調(diào)用。
另外還有兩個重要的接口:Test和TestListener。
1.Test, 包含兩個方法:run() 和countTestCases(),它是對測試動作特征的提取。
2.TestListener, 包含四個方法:addError()、addFailure()、startTest()和endTest(),它是對測試結(jié)果的處理以及測試驅(qū)動過程的動作特征的提取。
下面給出的兩個類圖(篇幅有限,只顯示主要部分)很好地闡明了類之間的關(guān)系,以及junit的設(shè)計目標(biāo)(如圖1)。測試案例的類采用Composite模式。這樣,客戶的測試對象轉(zhuǎn)變成一個“部分—整體”的層次結(jié)構(gòu)?蛻舸a僅需要繼承類TestCase,可以輕松的與已有的其他對象組合使用,從而使得單元測試的集成更加方便。
圖1 測試結(jié)構(gòu)圖
圖2是測試跟蹤類圖。
圖2左邊TestSuite包含了測試對象集合,右邊包含了測試結(jié)果集。具體如何處理結(jié)果,以及包含哪些測試對象,并沒有立即得出結(jié)論,而是盡量地延遲到具體實現(xiàn)的時候。例如,實現(xiàn)接口TestListener的JUnit中含有:junit.awtui.TestRunner、junit.swingui. TestRunner、junit.ui.TestRunner等,甚至客戶用自己的類實現(xiàn)TestListener,從而達到多樣化的目的。
從以上兩個類圖,可以了解JUnit對單元測試的基本思路,這個框架的核心是結(jié)果集和案例集。