最近機緣巧合快毛,又一次讀到好幾篇關于爭論TDD是否還活著格嗅,以及它到底好不好用的問題。似乎在幾年前DHH那篇檄文后唠帝,過一段時間就會聽到一次余響吗浩。
這也促使我對反思了一下自己對TDD是什么,TDD與Unit Test的關系没隘,TDD實用么等問題的看法懂扼。
TDD是什么
可以從它的名字切入:
-
Test —— 測試,可以不是單元測試右蒲,可以沒有一層層的mock阀湿,甚至可以不能作為程序執(zhí)行,不能自動判斷結(jié)果……
但是有一條是測試的關鍵
無二義的成功/失敗標準瑰妄。
換句話說陷嘴,在給定的上下文中,測試要么成功间坐,要么失敗灾挨。且項目所有成員對此都有共識。
缺少這點竹宋,測試就退化為寬泛的功能規(guī)范劳澄,接著就會出現(xiàn)“完成了80%”,“已經(jīng)開發(fā)完了蜈七,只需要調(diào)好一個bug”這樣的進度黑洞秒拔。 -
Driven —— 驅(qū)動有兩層含義,一個是嚴格意義上浮現(xiàn)式設計要求的寫測試之前不能寫生產(chǎn)代碼飒硅。如果說奧卡姆剃刀是“如無必要砂缩,勿增實體”那么TDD則是“如無測試作谚,勿增實體”。
這一部分也許過于嚴格庵芭,有爭議妹懒。但是從另一方面來看Driven可以看作是對整個軟件發(fā)展過程提供保駕護航的作用。就像是司機替我們操心了交通情況双吆,我們就可以在上下班路上解放腦子刷刷朋友圈眨唬,讀讀書什么的。
沒有Test提供的快速伊诵,持續(xù),統(tǒng)一的反饋回官,軟件的進展很容易就脫軌了曹宴。
很多測試用例的要求和具體技術,其實都只是為了這種反饋的目的而設計的歉提。比如說UT和Mock笛坦,是為了測試更快速,而不是說這樣才是TDD苔巨。 -
Development —— 開發(fā)版扩,TDD是直接關于開發(fā)的,也就是說測試描述的行為要直接體現(xiàn)在可執(zhí)行的交付物中侄泽。
這是我為什么不認同把ATDD與UTDD并舉的說法礁芦。驗收測試的循環(huán)中(ATDD)包含著非常多小的TDD循環(huán),就像是程序中的遞歸或者自相似的分形結(jié)構(gòu)一樣悼尾。
ATDD是在單元的TDD基礎上的自然延伸柿扣,而不是割裂的另一個概念」胛海或者這樣說未状,一個小系統(tǒng)的ATDD,放到更大的范圍內(nèi)析桥,可能也只是系統(tǒng)的一顆螺絲釘而已司草。這時候莫不是要提出AATDD不成?
另一方面泡仗,這也是為什么我不理解TDD必須要xxx埋虹,yyy配合才能做成的說法。在我看來TDD是非趁湓酰基礎的實踐吨岭,是它給其它更高層面的技術和理念提供支持,而非相反峦树。
這就像如果沒有Git之類的版本管理工具辣辫,敏捷開發(fā)是不可想象的旦事。但是絕不是說,只有采用了敏捷方法才能用起來Git急灭。
TDD也是類似姐浮,歸根結(jié)底是一種更高效的寫代碼的技術。比如我就把TDD看作是一種主動debug的手段葬馋。它在這方面起到的作用也就和一個調(diào)試器這種工具差不多卖鲤。
是否使用某種工具,是否花時間來學習工具為將來提高效率畴嘶,應該是程序員為自己作出的決定蛋逾。
我的兩個標準
當然如果用了工具,有時結(jié)果也不理想窗悯。
那么有兩種可能区匣,要么這個工具不好用,或者至少對要解決的問題不好用蒋院。要么亏钩,使用者還沒有完全掌握用法。
我的兩個檢驗標準欺旧,來檢驗TDD是不是真的發(fā)揮了作用姑丑。
- 團隊方面:
- 團隊內(nèi)review代碼時,是先看測試還是先看實現(xiàn)代碼辞友?
- 你的代碼寫好要和其他人對接時栅哀,他是跑來問你要文檔/要你口頭解釋,還是去看你的接口測試称龙?
- 個人方面:
你接手了一段遺留代碼要改一個bug昌屉,無文檔,無測試茵瀑,當初開發(fā)人員也走了间驮。
你已經(jīng)跑起程序,重現(xiàn)出了bug马昨,并開始嘗試修改代碼調(diào)整程序行為竞帽。
這時你會情不自禁說出哪句話?
- 算了太麻煩了鸿捧,不用寫測試了吧
- 算了太麻煩了屹篓,還是先寫幾個測試吧