前面的一篇文章(單元測試------理論篇)討論了什么是單元測試、單元測試的優點并列舉了很多不寫單元測試的借口。如果你同意我們的觀點,認同單元測試確實是軟件開發中不可缺少的過程,那么我們就開始單元測試之旅吧!
一個比較最大值的函數
我們首先引入一個比較最大值的函數。我們傳入一個類型為int的數組參數,它將返回最大值的那個元素。代碼如下:
public class Largest { public static int largest(int[] datas){ int max = 0; for(int i = 0 ; i < datas.length ; i++){ if(max < datas[i]){ max = datas[i]; } } return max; } } |
可是,如何寫我們的測試代碼呢?
直接在Largest類中添加一個main方法,要么重新寫一個可運行的類來測試Largest。這樣的測試,同樣給我們帶來了很大的挑戰:
1、驗證困難。如何去驗證代碼的行為和我們的期望一致呢?使用很多的if…else再加上==或equals()來判斷?對異常的情況又如何處理呢?混亂的驗證,很容易給我們的測試代碼帶來BUG,讓我們對自己的測試不夠自信。
2、測試類無法管理。我們如何直觀的得到測試運行成功或失敗的消息?用原始的System.out.println()嗎?我們能一次運行多個單元測試嗎?如果前面的測試運行出現異常,后面的測試還能繼續運行嗎?如果測試類很多,上百個甚至更多,我們能方便的由控制臺輸出測試結果嗎?
3、無法統計測試代碼覆蓋情況。缺少統一的測試代碼編寫規范和約定,可讀性和維護性差。
不過,面對這些挑戰不用沮喪。單元測試框架已經幫我們解決了這些問題,它提供了很多測試的基礎設施,讓我們能把更多的經歷投入到測試代碼的編寫中來。
JUnit
JUnit最初是由Erich Gamma(GoF之一)和Kent Beck(xp和refactor的先驅之一)編寫的,它是一個開源的Java測試框架,用于編寫和運行可重復的測試。
下面我們逐步介紹如何對Largest類測試:
一、JUnit的安裝。如果你使用的開發工具是Eclipse,不用做任何安裝,它已經提供了Junit的支持。否則,你需要去http://www.junit.org/下載Junit安裝包。安裝非常簡單,只要將junit.jar包設置到ClassPath中,讓你的Java代碼能夠找到它就可以了。
二、編寫測試代碼。代碼如下:
public class LargestTest extends TestCase { public void testLargest(){ int[] datas = {7,8,9}; assertEquals(9,Largest.largest(datas)); } } |
說明:
1、測試類一般要繼承抽象類TestCase。它實現了各種測試方法,并提供了一個測試過程的架構。
2、測試代碼通過斷言(Assert)來判斷某個被測試函數是否正常工作。JUnit提供了很多斷言函數,用來確定:某個條件是否為真;兩個數據是否相等,或者不等,或者其它的一些情況。
3、測試方法名以“test”開頭,這樣JUnit框架會自動發現這是一個測試方法。
三、運行測試類。
運行測試成功。
我們的單元測試這樣就算完成了嗎?不,上面的測試只能算是一次驗證而已。我們給的數據中,最大值9是數組的最后一個元素,如果9是第一個元素它還正確嗎?如果數據是負數呢?等等。我們的求最大值函數有著很多的邊界情況需要單元測試來驗證。
因此,我們在寫單元測試之前,一定要對測試做一個周全的計劃,預先設置好要測試的內容,可能發生錯誤的邊界條件。
下面是對Largest做的測試計劃:
1、數組元素的位置是否對最大值產生影響?
[7,8,9] – 9
[7,9,8] – 9
[9,8,7] – 9
2、如果有兩個相等的最大值,會出現什么情況呢?
[7,9,8,9] – 9
3、如果數組中只有一個元素,結果會怎么樣?
[1] - 1
4、如果元素都是負數呢?
[-7,-8,-9] - -7
完整的測試代碼應該如下:
public class LargestTest extends TestCase { public void testSimple(){ assertEquals(9,Largest.largest(new int[]{7,8,9})); } public void testOrder(){ assertEquals(9,Largest.largest(new int[]{7,9,8})); assertEquals(9,Largest.largest(new int[]{9,8,7})); } public void testDups(){ assertEquals(9,Largest.largest(new int[]{7,9,8,9})); } public void testOne(){ assertEquals(1,Largest.largest(new int[]{1})); } public void testNegative(){ assertEquals(-7,Largest.largest(new int[]{-7,-8,-9})); } } |