為了節(jié)省篇幅,上面的測試代碼省略了某些內容,例如當isDivisor方法的第二個參數(shù)是負數(shù)時會出現(xiàn)什么情況。
用javac *.java命令編譯這個類,然后輸入java CalculatorTest運行它。
你應該得到一個“不能判斷小于2的數(shù)是否素數(shù)”的運行時異常。大概形式如下,當然顯示的行數(shù)36可能因為你處理CalculatorTest.java中空格的方式而有所不同:
Exception in thread "main" java.lang.RuntimeException: isPrime should throw exception for numbers less than 2
at CalculatorTest.main(CalculatorTest.java:36)
換句話說,F(xiàn)actorCalculator的功能不正確。在isPrime方法前面加一個判斷可以解決這個問題,判斷參數(shù)小于2時拋出IllegalArgumentException異常。像下面的一小段代碼:
if (number < 2) {
throw new IllegalArgumentException();
}
把上面的代碼放到FactorCalculator的isPrime方法的前面。為了便于你參考,修改后的isPrime方法列在FactorCalculator.java.v2中,如果你打算直接使用這個文件,先把它改名為FactorCalculator.java。
增加了檢查后,重新編譯運行CalculatorTest,新的CalculatorTest應該可以通過所有測試。
三、JUnit提供測試框架的優(yōu)勢(JUnit Provides Advantages as a Test Framework)
測試Java類的內部功能是剛才你做的那些工作了。真正的測試和剛才的簡單例子的主要區(qū)別是代碼庫的大小和復雜度。在處理一大堆代碼時,你會需要收集情況報告。但上面的例子遇到第一個錯誤停止了,它沒有收集盡可能多的錯誤信息,也不能報告那些測試可以通過。如果一個測試不通過,把整個測試重新編譯、運行一遍,那開發(fā)過程肯定會非常慢。Bug經常是相互關聯(lián)的,而且由各部分代碼交互的地方引起。一次看到多個錯誤可以幫你分析和解決bug,對有關聯(lián)的bug的處理也會加快。
在使用JUnit重寫這個測試之前,你需要了解下述術語和測試概念:
1、單元測試(Unit test):單元測試是指一小段代碼——絕大多數(shù)情況下都只有一個Java類——測試一個軟件或者庫非常有限的一個部分。單元測試檢驗的代碼都很小,例如一個或幾個類。通常是測試EJB組件和普通Java類庫,不管這些類在服務器端(容器)環(huán)境中還是獨立運行。與列表中提到的另一個概念功能測試比起來,單元測試的主要區(qū)別在于,單元測試的重點是終用戶一般看不到的內部組件,而功能測試的重點是“點擊按鈕”。在JUnit中,單元測試可能是TestCase類中的一個方法,也可能是整個TestCase類。從大小上講一兩頁的代碼對單元測試應該是合適的。如果單元測試達到十頁太夸張了,分成若干個粒度更細的測試會比較好。
2、功能測試(Functional test):功能測試是站在終用戶的角度驗證程序的功能是否正確。功能測試和黑盒測試是同一個意思。
3、黑盒測試(Black box test):黑盒測試是只根據(jù)對外發(fā)布的接口或公共約定,而忽略程序內部實現(xiàn)進行的測試。這通常意味著你只知道應該輸入什么,只測試預期的輸出,不知道程序如何生成這些輸出,性能、邊界影響等其它外部特征也不在你的考慮范圍內,除非代碼的這些方面特性是公共約定的一部分。如果你開發(fā)的軟件庫中有提供給其它開發(fā)者(你的終用戶)使用的API,黑盒測試顯得尤為重要。這個重要性不僅僅是指軟件庫能按公共接口說的做,軟件庫避免公共接口中禁止或省略的內容也很重要。如果你開發(fā)一個程序,遵守公共接口也是很重要的,因為它使你和同事之間能更有效的合作。
4、白盒測試(White box test):白盒測試是在知道代碼如何實現(xiàn)的情況下測試一段代碼的功能。當你要測試公共約定中沒有指定,但很重要的行為,例如性能問題時,白盒測試派上用場了。在測試某些特別復雜的算法或業(yè)務邏輯時,也需要白盒測試。這種情況下,通過白盒測試你可以把注意力集中在可能出現(xiàn)錯誤的地方,這在黑盒測試中由于缺乏對內部情況的了解很難做到。
5、容器內測試(In-container test):容器內測試在servlet或EJB容器內部進行,因此能更直接的和要測試的代碼通信。Jakarta Cactus項目實現(xiàn)了一個免費的測試工具Cactus,它讓你和要測試的代碼在同一個容器內執(zhí)行,不管這個容器是servlet容器還是EJB容器。容器內測試對黑盒功能測試沒什么用,它的作用體現(xiàn)在單元測試上。
6、測試用例(Test case):Test case在JUnit中是一組相關的測試。Test case表現(xiàn)為繼承junit.framework.TestCase的類。Test case通常有多個方法,每個方法測試程序一方面的行為。Test case中的測試方法習慣用test作前綴命名,但并不是必須這樣做,只要不與其它方法產生沖突可以。
7、測試集(test suite):Test suite是一組test case或test suites。它表現(xiàn)為繼承junit.framework.TestSuite的類。沒有任何限制要求test suite只包括test case或只包括test suite,它可以既有test case,又有test suite。一個test suite的子test suite也可以包括test case和test suite,因此允許嵌套測試。只要你愿意,你可以建立幾組test case,每一組測試程序的一個明確的小方面。一組可以形成一個test suite。然后你可以把它們綜合到一個主test suite中,后用這個主test suite測試整個程序,一個功能點一個功能點的測試。
8、測試啟動器(Test runner):Test runner是啟動測試過程的JUnit類。你調用test runner,它依次執(zhí)行你預訂的測試。有幾種辦法可以定義要test runner執(zhí)行的測試。這些辦法在下面的第五部分“指定要運行的測試”中介紹。JUnit有三種不同的test runners:text、AWT和Swing,類名分別是junit.textui.TestRunner、junit.awtui.TestRunner和junit.swingui.TestRunner。