TDD的简单实践
最近有幸跟隨資深ThoughtWorks咨詢師熊節老師一起學習測試驅動設計,經過短暫的十幾天培訓,對測試驅動設計的基本原則、實踐模式、技巧有了一點點初步的認識。
在此之前,經常自嘲我經歷的公司實踐也似乎是TDD, 這種實踐往往都是由測試工程師來驅動開發者完成bug的修改,雖然也是測試來驅動開發,但是卻與真正的TDD大相徑庭。
什么是TDD在維基百科中是這樣對TDD下定義的:
測試驅動開發(英語:Test-driven development,縮寫為TDD)是一種軟件開發過程中的應用方法,由極限編程中倡導,以其倡導先寫測試程序,然后編碼實現其功能得名。測試驅動開發始于20世紀90年代。測試驅動開發的目的是取得快速反饋并使用“illustrate the main line”方法來構建程序。 測試驅動開發是戴兩頂帽子思考的開發方式:先戴上實現功能的帽子,在測試的輔助下,快速實現其功能;再戴上重構的帽子,在測試的保護下,通過去除冗余的代碼,提高代碼質量。測試驅動著整個開發過程:首先,驅動代碼的設計和功能的實現;其后,驅動代碼的再設計和重構。測試驅動開發也是國外許多優秀開發者向開發者們推薦的一種普遍適用的開發模式,而在熊節老師的培訓課程中,他時刻在向開發者灌輸來自TDD的三條原則,要求我們的編寫生產代碼前,一定應該先編寫單元測試。
定律一:在編寫不能通過的單元測試前,不可編寫生產代碼。 定律二:只可編寫剛好無法通過的單元測試,不能編譯也算不通過。 定律三:只可編寫剛好足以通過當前失敗測試的生產代碼。 簡單實踐在我之前的編碼實踐過程中,總是習慣梳理一遍邏輯后,在根據項目的實際情況對代碼進行重構,而隨著我自以為掌握了單元測試的技巧之后,就開始把邏輯代碼往單元測試上套,導致這樣的單元測試實際上并非為了實現測試,而僅僅只是程序的入口而已。
如果使用TDD的方法,則需要首先規劃需要實現的目標,然后再定義測試方法和測試需要實現的邏輯。
例如,代碼大概是這樣的:
我的目標是實現對Schema對象的解析,測試類采用SchemaUnitTest,并采用“should_xxx_when_xxx”的命名方式,定義了測試方法“should_return_true_when_bool”,然后定義一個Schemas的類,再定義其需要實現的需求(斷言),以及需求的實現。
對單元測試方法的命名,不同的書籍有不同的命名方法,在這個項目實踐中,采用的是should命名方法,而在之前看過的《單元測試的藝術》一書中,使用的is_when_return_xxx的方式,這兩者只是命名方法的不同,本質上沒有任何區別;使用xunit和mstest實際上也沒有太多區別。
此時,這個定義的方法GetParameter是未實現的,所以會進入一個“紅-綠-重構”的工作流程。
?
1)編寫一個會失敗的測試,以證明產品中代碼或功能的缺失。編寫代碼時,要假設產品代碼已經能工作了,這樣測試的失敗就說明產品代碼中有缺陷。例如我定義的GetParameter方法使用xunit進行測試會提示失敗, 只有在添加需要的代碼后,編譯才能通過。
2)編寫符合測試預期的產品代碼,使測試通過,產品代碼應該盡量簡單。
3)重構代碼。如果測試通過了,你就可以編寫下一個單元測試,或者重構,消除異味或提高代碼可讀性。
最終,我完成了一個這樣的方法。(即便是這樣的代碼,依然有許多可以進一步提升的空間。)
顯然這是一個邏輯非常簡單的代碼,但是如果采用全鍵盤操作,不使用鼠標來完成,仍然耗費了我不少時間,這個過程中,也讓我對Visual Studio的快捷鍵操作更加熟練。
測試的不同階段在我們的產品研發過程中,經常遇到以下三種不同形式的測試
- 端到端測試:端到端測試側重于軟件功能應用層面的測試,主要使用人工或自動化的形式對用戶界面進行測試。往往需要覆蓋系統的各個功能,需要耗費的人力物力較大。
- 服務測試:主要集中在服務接口層的測試,可以通過PostMan等測試工具對接口的穩定性和可用性進行測試。側重于接口行為實現。
- 單元測試:針對代碼層面,例如單個方法或單個類實現的測試。屬于白盒測試的一種。
三種測試從上到下實施的容易程度遞增,但是測試效果遞減。端到端測試最費時費力,但是通過測試后我們對系統最有信心。單元測試最容易實施,效率也最高,但是測試后不能保證整個系統沒有問題。
在我們的項目實踐中,更多的采用的依然是端到端測試的模式,似乎只有通過測試者的人肉測試,才能讓我們的代碼更加令人滿意。
單元測試事實上極少在我們的項目中得到實踐,其主要原因大概是因為要掌握單元測試方法,本身需要對開發者的主觀能動性提出了更高的要求,但是996開發者...太容易內卷化了。
總結寫好單元測試從來就是技術活,有一段時間過分在意理論概念和工具的用法,忽略了實踐,所以實際上看了好幾本書,依然不知道如何寫單元測試,這次參與了培訓,終于摸到了一點點影子。
現階段我大概可以這樣做來逐步提高自己的技能水平:
- 1、小步快跑,注意節奏:不要過度在意某個需求的快速實現,而是編寫能夠在五分鐘內快速完成的代碼,并確保其通過。代碼行控制在五行以內,代碼的縮進層次,控制在兩到三層。
- 2、練習,練習,再練習:寫代碼從來不是一件容易的事情,按照一萬小時定律的說法,如果指望幾天就熟練掌握顯然不太現實,未來需要更加積極的練習,才能真正掌握。
- 多思考、努力寫好代碼:寫幾行代碼其實并不難,難的是寫高質量的代碼。不要急于代碼實現,要多思考上下文邏輯,讓代碼更加優美。
參考資料:
- https://docs.microsoft.com/zh-cn/dotnet/core/testing/unit-testing-best-practices
- https://juejin.im/post/5c715e7d6fb9a04a0c2f12f4
轉載于:https://www.cnblogs.com/xiyuanMore/p/11565199.html
總結
- 上一篇: Are We Ready for SDN
- 下一篇: 项目失控全记录