2015-07-11 29 views
0

我們正在嘗試使用TDD來創建我們的系統,並且我們遇到了一個我們無法弄清楚正確的TDD行動方案的情況。TDD - 如何測試.Read()沒有.Write()?

我們已經隱藏文件IO接口後,像這樣:

public interface IFileIo 
{ 
    byte[] Read(string fileName); 
    void Write(string filename, byte[] data); 
} 

,現在我們正在創建一個InMemoryFileIo,我們可以代替真正的SystemFileIo類,我們將使用生產使用。

我們希望確保這個InMemoryFileIo正常工作,並且可能有些情況下我們想用它來代替實際的文件系統,所以它應該是「生產質量」。

問題是,做所有「正確的TDD方式」,我們如何創建一個測試.Read().Write()他們不相互依賴?

爲了測試這工作正常,我們會需要.Read()成功地打了一個電話給.Write()第一,同樣,來測試.Write()工作正常,我們會再需要調用.Read()之後。通過這樣做,我們實際上創建了兩次相同的測試(安排,然後寫入,然後讀取,然後斷言)。

可以說我們有兩個測試,一個測試.Read(),另一個測試.Write()。如果其中任何一個功能都不起作用,那麼這兩個測試都會失敗。這違反了「一個測試應該只有一個失敗原因」的原則。

這裏的例子是文件IO,但是當使用數據庫時測試put沒有get這個問題。

+1

在這種情況下沒問題,只是一起測試它們 - 如果失敗,則意味着另一個失敗,並且測試中的錯誤消息會告訴您哪一個失敗。不要反套,也不要試圖使用任何模擬思考的東西 - 它在同一個單元內,這是有道理的。 –

+2

對於InMemoryFileIo而言,「正確」的方式(再次擔心它)將在其構造函數中使用byte []而不是創建它(依賴注入),這將允許您預先設置數據讀取或運行對彼此外部編寫的數據的檢查 - 實際上,不要過度考慮這一點 - 只需編寫對您有意義的測試,並幫助您明確識別系統中的缺陷。 –

+0

我認爲值得指出的是,如果你的內存IO類只是作爲測試的雙倍使用,它應該足夠簡單,不需要進行大量的測試。重點是假的其他類你TDDing取決於接口的權利?耦合他們的傳遞或不通過測試,以確定您的內存中的文件IO假是否無缺陷似乎對我來說可能是一個壞主意。我建議讓你的存根很簡單。 – kai

回答

2

整個問題歸結爲你如何定義你的「單位」。就我個人而言,將「單元」看作是一組連貫的行爲而不是單一的方法調用會有幫助。

Roy Osherove單位定義爲:

單元測試是一個自動化的一段代碼調用系統中的工作單元,然後檢查關於工作單元的行爲的單一假設。工作單元是系統中的一個邏輯功能用例,可以由一些公共接口(大多數情況下)調用。一個工作單元可以跨越單一方法,整個班級或多個班級一起工作實現一個可以驗證的邏輯目的。

因此,最後拋開所有的指導方針,如果它沒有意義的分開閱讀/寫作責任,你只是組合測試它們。一般來說,當我覺得沒有簡單明瞭的方法來驗證通過後門測試的結果(不管是可以被模擬的合作者,還是一些狀態驗證,...),我都沒有問題公共API的其他功能。這些通過公共API執行組件的測試通常不會像使用後門進行驗證的測試那麼脆弱。