測試驅動開發TDD | IDCF FDCC認證學員作品

DevOps訂閱號發表於2020-07-06


一、TDD是什麼

測試驅動開發TDD  | IDCF FDCC認證學員作品



測試驅動開發(Test-Driven Development,TDD)是敏捷開發中的一項核心實踐和技術,也是一種設計方法論。TDD的原理是在開發功能程式碼之前,先編寫單元測試用例程式碼,測試程式碼確定需要編寫什麼產品程式碼。TDD雖是敏捷方法的核心實踐,但不只適用於XP(Extreme Programming),同樣可以適用於其他開發方法和過程。
TDD的基本思路就是透過測試來推動整個開發的進行,但測試驅動開發並不只是單純的測試工作,而是把需求分析,設計,質量控制量化的過程。
TDD的重要目的不僅僅是測試軟體,測試工作保證程式碼質量僅僅是其中一部分,而且是在開發過程中幫助客戶和程式設計師去除模稜兩可的需求。TDD首先考慮使用需求(物件、功能、過程、介面等),主要是編寫測試用例框架對功能的過程和介面進行設計,而測試框架可以持續進行驗證。

“測試驅動開發不是一種測試技術。它是一種分析技術、設計技術,更是一種組織所有開發活動的技術”。 
——Kent Beck(TDD之父)


二、TDD需要考慮什麼

測試驅動開發TDD  | IDCF FDCC認證學員作品



TDD需要考慮下幾點:
2.1 開發人員的開發意識
開發人員對於軟體質量,常常偏重於軟體的外部質量,體現在他們的工作KPI設定,就是被測試人員發現的缺陷數。開發人員不適合做測試思想作怪,從而可能忽略真正需要測試的用例。開發人員編寫測試帶來的收益,最重要的一點不在於測試本身,而在於它能促進開發、測試以及需求分析人員的交流與溝通。而測試先行的方式也能讓開發者從業務角度去看待問題,從客戶角度去思考介面。此外,由於開發者總將測試職責委派給了專門的測試人員,於是漸漸會產生一種依賴心理。這種測試帶來的反饋週期太長,一旦發現缺陷,修復的成本很高。
2.2 分析需求,任務分解
需求分析能力常常是開發人員的短板。開發人員養成了一個習慣,看什麼事情都會從技術實現的角度去思考,很少從客戶角度考慮,也很少從考慮需求因何而來,這個需求的價值是什麼,這個需求的關鍵點在哪裡。
對於需求描述,我們沒有深入瞭解,大多數掌握了大體後,就匆匆進行開發與實現。TDD要求我們在編寫測試之前要做好合理的任務分解。若沒有很好地理解需求,任務分解就無法順利的進行。
從使用者價值出發,先梳理出最外層的需求任務,自上而下分解。基本上,任務拆分步驟:業務價值->業務功能->業務實現。
2.3 測試先行的開發習慣
測試先行開發習慣的問題,不是一朝一夕可以完成的。主要兩個方面:

  • 測試先行為何物

以我個人多年工作經驗,詢問過了很多開發人員,很多人都不清楚什麼是TDD開發方法,更何況測試先行是什麼。

  • TDD方法的掌握有一些誤解導致

在改變為測試先行的時候,錯以為應該一上來就寫測試。因為思路沒有理清,腦子裡是一片亂麻,加上對TDD不夠熟悉又不願意寫測試程式碼(都是測試乾的活、憑什麼這工作歸到我手上的觀念作怪),於是編寫測試就變得舉步維艱。
在開始測試驅動開發之前,做適度的事先設計,還有利於我們仔細思考技術實現的解決方案。它與測試驅動介面的設計並不相悖。解決方案或許屬於實現層面,若過早思考實現,會干擾我們對介面的判斷;但完全不理會實現,又可能導致設計方向的走偏。
2.4 開發人員的重構

測試驅動開發TDD  | IDCF FDCC認證學員作品

  • 不可執行——寫一個功能最小完備的單元測試,並使得該單元測試編譯失敗。

  • 可執行——快速編寫剛剛好使測試透過的程式碼,不需要考慮太多,甚至可以使用一些不合理的方法。

  • 重構——消除剛剛編碼過程引入的重複設計,最佳化設計結構。

重構的關鍵首先在於如何識別程式碼的壞味道, 需要閱讀一定規模優秀的開原始碼,當這些壞味道變成你的一種直覺,你就會降低對糟糕程式碼的容忍度。

重構手法與程式碼壞味道一一對應。若有測試保障,重構就變得安全。但儘可能地,我們還是希望運用工具提供的自動重構功能,這既提高了重構效率,也在一定程度下確保了重構的安全。

2.5 單元測試

確定開發人員編寫,測試函式/方法粒度,程式碼正確性檢驗方式(尤其測試資料),編碼前後和修改程式碼時透過單元測試。


三、TDD實踐

測試驅動開發TDD  | IDCF FDCC認證學員作品



3.1 思考要做什麼,如何測試它,然後編寫一個測試(所需的介面型別、輸入和資料)。

例如:

測試驅動開發TDD  | IDCF FDCC認證學員作品

3.2 編寫code使測試失敗(明確失敗比模糊好)。

測試驅動開發TDD  | IDCF FDCC認證學員作品

  • 執行失敗code

測試驅動開發TDD  | IDCF FDCC認證學員作品

3.3 編寫剛剛測試透過code(確保之前編寫的測試)。

測試驅動開發TDD  | IDCF FDCC認證學員作品

  • 執行成功的code

測試驅動開發TDD  | IDCF FDCC認證學員作品

3.4 執行獲取測試結果。如果沒有透過,則立刻解決它。

示例:

測試驅動開發TDD  | IDCF FDCC認證學員作品

3.5 如果有重複的邏輯或無法解釋的程式碼,立刻重構(減少耦合,增加內聚力)。再次執行測試驗證重構是否引入新的錯誤。如果沒有透過,很可能是在重構時犯了一些錯誤,需要立即修復並重新執行,直到所有測試透過。

  • 重構前:

測試驅動開發TDD  | IDCF FDCC認證學員作品

  • 重構後

測試驅動開發TDD  | IDCF FDCC認證學員作品

  • 執行結果:

測試驅動開發TDD  | IDCF FDCC認證學員作品

3.6 重複01-05上述步驟,直到找不到更多驅動編寫新程式碼的測試。

測試驅動開發TDD  | IDCF FDCC認證學員作品


四、TDD難點

測試驅動開發TDD  | IDCF FDCC認證學員作品



4.1 小步迭代,具體迭代是粒度多少?
DD 建議是採用儘量小的迭代(測試無法再拆分,微小的重構),但是也沒有強制一定按照這種步伐,不同人定義粒度不同,可在實踐中獲取適合自己的粒度,但前提必須儘量小。
4.2 TDD 是銀彈嗎?
TDD 不是銀彈,不可能適合所有的場景,遇到問題還需要具體問題具體分析,尋找最佳實踐。
4.3 不遵循不可執行->可執行->重構是否可以?
Kent Beck(TDD之父) 沒有說明,也沒有專門的人真正去做過這個統計。
4.4 為什麼每次在可執行階段只編寫“可用”程式碼?
因為要儘快使測試執行起來,儘快縮短反饋時間,持續保持小步迭代的節奏。效率高,可產出優雅的code。

四、總結

測試驅動開發TDD  | IDCF FDCC認證學員作品



TDD提供一種更快、更優雅、更安全的程式碼開發方式。

“程式碼簡潔可用這句言簡意賅的話,正是 TDD 所追求的目標”
——《Test-Driven Development》Kent Beck

參考文章

  • 《重構》
  • 《測試驅動開發》
  • Test-driven development:https://en.wikipedia.org/wiki/Test-driven_development
  • Lyning技術部落格:

測試驅動開發TDD  | IDCF FDCC認證學員作品

- 作者:陳思宇 - 
程式猿/ACP/PMP/ACP/P2/DOP/SA5.0/DevOps社群志願者。
測試驅動開發TDD  | IDCF FDCC認證學員作品

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31558019/viewspace-2702589/,如需轉載,請註明出處,否則將追究法律責任。

相關文章