《單元測試的藝術》閱讀二

1.1 名詞定義

單元測試框架 用於編寫、運行和查看單元測試及其結果的,容易編寫的,可重複使用的,並能覆蓋到測試代碼的所有重要部分的框架

狀態驗證 通過檢查被測試的系統與協作方在被測試方法執行後行爲的改變,判定被測試方法是否正確工作

1.2 第一個單元測試

這是一段需要被測試的代碼(在這裏需要注意對於類和方法的明明規則,也就是編程規則):

public class LogAnalyzer {
    public boolean IsValidLogFileName(String fileName){
        if (fileName.endsWith(".SLF")){ return  false; }
        return true;
    }
}

單元測試的三個行爲:準備對象(Arrange),操作對象(Act),預測對象的某個行爲(Assert)。
所以按照這三個行爲編寫一個測試方法:

public void IsValidFileName_BadExTension_ReturnFalse(){
    LogAnalyzer analyzer = new LogAnalyzer();
    boolean result = analyzer.IsValidLogFileName("filewithbadextension.foo");
    if (!result){
        //do something;
    }
}

這是一個錯誤檢驗,先準備好對象並進行操作,最後預測其返回的是false,然後do something,然後我們還要增加一個正檢驗,邏輯上同理。得到全部測試通過之後,需要做的就是減少重複的測試代碼進行代碼重構,保證其簡潔易懂。

1.3 重構

如果LogAnalyzer方法需要加入一個參數,之前的測試就需要全部修改了,這明顯不符合重複使用的原則。因此這裏需要加上可選添加的參數,使其能替換所需位置(原書中使用的是.NET語言,直接使用TestCase屬性即可)。

然後還需要保證對於不同的測試都要重新創建對象,不能讓舊的對象影響到之後的測試結果,所以測試代碼可以修改,創建對象的部分可以單獨拉出來,在一次測試完成之後需要把對象置空(這都是比較基本並且不考慮後果的做法,實際開發需要根據情況改變方式)。
當然,這種創建對象和對象置空的方式,都會極大地增加代碼量,使得測試代碼的可讀性變差,如果兩年後你已離職,其他程序員再來讀你的代碼,或許就會在心裏策馬奔騰了。所以這種策略需要仔細考量使用的位置和方式。比如書上介紹的使用工廠方式來創建對象。

1.4 檢驗異常

書中記錄檢驗異常的例子中有一個比較經典的例子說明。

public class LogAnalyzer {
    public boolean IsValidLogFileName(String fileName){ 
        try {
            if (fileName.isEmpty()){
               throw new Exception("filename has to be provided");
           } 
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }
}

這段代碼就是在filename爲空的時候拋出異常,可是如果直接用上面的測試邏輯去檢測這個方法,會發現這一個方法都在一個大的try-catch裏面,如果構造函數有問題拋出異常,其實同樣也會使得測試通過。但構造函數絕不應該拋出異常。所以這個方法是不可取的。書中使用的是.NET的Assert.Catch 方法處理,在Java中應該有類似方法,之後再詳細進行相關學習

1.5 測試系統狀態改變

有時候測試的結果並不一定用返回值來檢驗,可能是系統狀態的改變或者某個顯示的變化,這些都是可以用來預測測試的結果的“工具”

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章