最近在讀 Uncle Bob 的書籍:Clean Craftsmanship,其中有解說到倫敦學派 TDD,覺得挺有趣想寫份筆記解說。
其中不只有倫敦學派的 TDD,還有芝加哥學派的 TDD,往後再特別寫一篇文章紀錄之。
倫敦學派 TDD 的核心原則
倫敦學派 TDD(也稱為「模擬派」或「外部-內部開發」)是由倫敦的開發者群體發展而來的 TDD 方法論。其核心原則包括:
-
外部-內部(Outside-In)開發:從系統的外部界面開始,逐步向內部實現。首先定義高層次的行為和介面,然後再實做底層細節。
-
關注交互而非狀態:倫敦學派更關注 component 之間的交互和協作,而不僅僅是單個 component 的狀態變化(如果和我一樣是後端開發者,可以想像成是關注 層級 之間的協作,而不是單個 方法 的狀態變化)。
-
大量使用 Mock:為了隔離被測試者,倫敦學派廣泛使用 Mock 物件來取代真實依賴。這使得測試可以專注於特定單元的行為,而不受其依賴項的影響。
-
行為驗證:通過驗證被測試者與其依賴之間的交互行為來確保系統正確性,而不僅僅是驗證最終結果。
-
設計優先:倫敦學派強調在實現之前先設計良好的介面和使用方式,測試驅動設計(TDD)同時也是設計的過程。
總結倫敦學派 TDD 的特性
倫敦學派 TDD 的特點如下:
特性 | 倫敦學派 |
---|---|
開發方向 | 外部-內部(Outside-In) |
測試焦點 | 行為和交互 |
模擬使用 | 廣泛使用 |
設計影響 | 強調接口設計 |
測試隔離 | 高度隔離 |
適用場景 | 複雜系統,多依賴 |
優點
倫敦學派 TDD 具有以下優點:
-
高度隔離的單元測試:通過模擬依賴,可以創建真正隔離的單元測試,使測試更加專注和快速。
-
介面驅動設計:促使開發者先思考介面跟使用的方式,有助於創建更好的系統設計。
-
快速反饋:由於測試是隔離的,執行速度通常很快,提供即時反饋。
-
適合複雜系統:對於具有多個層級和複雜依賴關係的系統,倫敦學派提供了更好的測試策略。
-
並行開發:一旦介面確定,不同層級可以由不同團隊並行開發,只需遵循已定義好的介面。
缺點或挑戰
倫敦學派 TDD 也面臨一些挑戰:
-
模擬可能與實現耦合:過度依賴模擬可能導致測試與實現細節耦合,使得改動一小部分會影響到多個測試。
-
測試脆弱性:當介面變化或是實作流程改變時,可能需要更新大量模擬和測試,增加維護成本。
-
學習曲線:正確使用模擬和掌握倫敦學派方法需要一定的學習和實踐。
-
模擬框架依賴:通常需要依賴模擬框架,增加了項目的依賴複雜性。
實踐建議
要有效實踐倫敦學派 TDD,可以考慮以下建議:
-
明智選擇模擬對象:不是所有依賴都需要模擬,對於無狀態的物件的依賴(例如:static class),可以使用真實對象。
-
關注 public interface:模擬應該基於 public interface 而非實現細節,這樣可以減少測試與實現的耦合。
-
避免過度規範:模擬不應該過度規範被測單元的行為,應該給予實現一定的靈活性。
-
共識的重要性:對於需要被公開且共用的 interface,應該共識其行為,待共識一致後再進行測試。
總結
倫敦學派 TDD 提供一個注重流程大於結果的 TDD 方法,是個非常有紀律的一種測試規範。但繼續伴隨而來的是測試的彈性較小,當開發者變動 production code 的流程或是介面即可能造成測試全壞,需要花費大量時間去修改測試。這卻是倫敦學派 TDD 的特點,他們認為用測試的彈性來換取系統的穩定性是值得的,因為他們認為測試的彈性較小可以確保測試的穩定性,進而確保系統的穩定性。
最後我自己看下來的想法: 沒有一定要選擇哪種學派來做 TDD 才是正確的,而是要視開發情境決定使用哪種 TDD 方法才對。