目錄
- PART I: 入門
- Chap 1: 單元測試基礎
- Chap 2: 第一個單元測試
- PART II: 核心技術
- Chap 3: 透過虛設常式解決依賴問題
- Chap 4: 使用模擬物件驗證互動
- Chap 5: 隔離(模擬)框架
- Chap 6: 深入了解隔離框架
- PART III: 測試程式碼
- Chap 7: 測試階層和組織
- Chap 8: 好的單元測試的支柱
- Chap 9: 在組織中導入單元測試
- Chap 10: 遺留程式碼
- Chap 11: 設計與可測試性
一、為什麼在設計的時候要關心可測試性
你可能現在正想著:「廢話!」不過真正的原因好像又不是那麼明確,因為此時你的目的似乎是要完成一些功能,而不是取悅似有似無、似是而非的「測試」,但其實你可以將「測試當成另一種使用者」。
在可測試性的設計中,單元測試具有以下特色:
- 執行速度快
- 相互隔離
- 不需要額外進行外部設定
- 穩定可靠的結果
如果撰寫這樣的測試很困難,或是需要很長的時間,那麼這個系統就不是一個可測試的系統。
二、可測試系統的目標
Uncle Bob 總結了可測試(OOD)的目標:SOLID
- Single responsibility principle(單一職責原則):指一個類模組包甚至系統都應該有單一的原則。
- Open-closed principle(開閉原則):你應該能夠擴充套件類的行為,而不需要修改它。
- Liskov substitution principle(里氏替換原則):簡答理解就是如果想要可替換的元件來構建軟體系統,那麼這些元件就必須遵守共同一個約定,以便讓這些元件可以相互替換。
- Interface segregation principle(介面隔離原則):使細粒度介面特定於客戶端,主要告誡設計師應該在設計中避免不必要的依賴。
- Dependency Inversion Principle(依賴倒置原則):依賴抽象,而非具體實現。此原則指出高層策略性程式碼不應該依賴實現的程式碼,相反,那些底層實現應該依賴於高層策略程式碼。
測試設計指南:
- 預設情況下將方法設定為虛擬方法
- 使用介面導向設計
- 預設情況,將類別設計成可繼承
- 避免在包含邏輯的方法內直接初始化類別執行個體使用,而是使用輔助方法、工廠模式、控制反轉容器
- 避免直接呼叫靜態方法
- 避免在建構式和靜態建構式中包含邏輯程式碼
- 把單例和單例的擁有者分開
三、可測試性設計的缺點
- 工作量:大多情況,會增加工作量,以 Bob 大叔為例,他會先使用簡單的設計,完成簡單的功能,然後只有在需要的時候進行重構。
- 複雜度:可測試性有時讓人覺得把事情複雜化了,有些介面讓人覺得彆扭,或抽象後的實作讓人覺得困難。
- 洩漏敏感的智慧財產權:可測試性會將一些方法強制公開,這種情況下,要嘛作出妥協,要嘛換工作。
- 有時無法進行:有時因應政策限制或其他原因,你不得不使用某種設計,因環境不允許,可測試性需要作出讓步。
小結
這一章,介紹了可測試性設計的概念。事實上,在現實世界中,可測試性設計的討論沒有簡單的答案。可測試性設計與 SOLID 設計原則息息相關,但是具備可測試性的設計不見得就是好設計。
也許,我們不該將可測試性設計當成最終目標,而是追求好的設計即可。
單元測試的藝術,到這兒就告個段落了,怎麼有種嘎然而止的感覺!
外面的世界還很精彩,攜著這些珍貴的知識,一起打天下吧!
番外篇:
其他推薦書籍
- Steve Freeman, Nat Pryce 的《Growing Object-Oriented Software, Guided by Tests》:設計方面的輔助內容
- Gerard Meszaros 的《xUnit Test Pattern: Refactoring Test》:單元測試模式和反模式
- Michael Feathers 的《Working Effectiverly with Legacy Code》:解決遺留程式碼