都別書生氣。在你編寫一個方法之前或是之后編寫單元測試--根據我的經驗,只要你在編寫代碼的幾乎同時就考慮并編寫單元測試程序,那么這就無關緊要了。過后再返回去(或者根本就不回去)寫測試程序將導致問題。就我個人而言,我喜歡在編寫少量代碼之前或緊接著的之后就編寫單元測試--這不會打破工作流程,因為它就是流程的一部分。
這需要一點兒實踐經驗--缺乏經驗的開發者經常為要寫什么樣的測試程序而煩惱。但這可能也反映出一個事實:他們同樣也不知道要寫什么樣的代碼。一些人評說TDD能夠鼓勵進行微設計--一種非常底層的設計,它不需要考慮較大的場景。這會發生在缺乏經驗的開發者身上;如果你教條般地應用這種方法,同樣也會遇上。像行為驅動開發這樣的方法在此處就會很酷。當你在寫getter方法之前,你會寫一個針對這個getter方法的單元測試嗎?如果是的話,那么你的單元測試專注的層次就較高了,也會更接近于用戶(或系統)的需求。
回到問題的本質,為什么我喜歡把單元測試放在最開始的位置?很簡單!我的實踐經驗告訴我,那樣可以幫助提高代碼的質量,并且節約調試時間。在開始時寫十個小的單元測試所花的時間比在以后修復Bug所花的時間要少,如果代碼經過了正確的單元測試,那就不會有Bug了。
事實上,我屢屢見到,如果某些代碼經過了適當的單元測試,那么就不會有編碼問題。最近就有一個例子:花了一個小時的時間去搜尋Web應用中的一個問題,該問題出現在一個編寫正確的Spring-MVC程序中。結果是由于一個檢驗器類忽略了一個異常。很容易就發現了這個問題,實際上,在看了代碼(代碼檢查(Code Review)也很有效)之后立刻就發現了。但關鍵是,我們花了一個小時甚至更多的時間去找這個需要進行檢查的類。如果這些代碼經過了適當的測試,那么就能很快地發現并解決這個問題。
根據我的經驗,當人們在編寫完程序之后才開始編寫單元測試,就如同事后才有這樣的想法,他們很難寫出這些測試了 ("我已經完成了所有的代碼,此時我還得去寫單元測試");蛘吒揪筒蝗プ。在這種情況下,代碼是否完成了呢?如果代碼運行地很好,那就算是完成了。這樣的話,再寫單元測試就大大地喪失了它的價值。還不僅如此,事后編寫的單元測試將是膚淺的,不會對代碼進行良好地測試;蛘,開發者已經耗完了時間,他們根本就不想再為單元測試傷神了。
TDD與任何其它的編碼實踐一樣。當你正在學習某個新的技術時,你會傾向于對學習指導亦步亦趨。類似地,當你學習一項武術時,你也會試著一步步地模仿大師的動作,而不必去理解其中的邏輯。一旦,你熟悉了某個技術,能夠熟練地使用它,并對它有了更深入地理解,之后,你就能改進它,并與你之前掌握的其它技術進行溶合了。
譯注
[1]John是Java Power Tools一書的主作者,也是java.net中一位活躍的Bloger。
譯后
上周在java.net上看到這篇Blog,再聯想到自己在平時工作中的單元測試實踐,有些感觸,故將其翻譯了出來,與大家共享。
事先就編寫單元測試,還是事后才編寫單元測試?這是一個老問題。按照TDD的思想,自然是要先編寫單元測試,然后再編寫能夠通過該單元測試的方法。
但,單元測試并不是TDD的專屬領地,很多不實踐TDD的項目也在應用著單元測試。
我認為,在不實踐TDD的項目中(我自己所處的環境就是如此),事后編寫單元測試仍有著其合理性:
1. 以消極的態度來看,既然項目本身不嚴格要求事先編寫單元測試,那么就可以在事后去做了。這至少比不去做要好,聊勝于無嘛。(嘿嘿,是夠消極的,但也拿你沒辦法)
2. 事后編寫單元測試至少也是一種檢驗手段,當然,肯定比不上事先編寫的單元測試。因為,事后編寫的單元測試很可能會"將就"已經寫好的應用程序,正如John所說"事后編寫的單元測試將是膚淺的,不會對代碼進行良好地測試"。但...仍然是聊勝于無嘛 :-D (哈哈,有完沒完了)
3. 可以把單元測試,其中就包含事后單元測試,作為"后來者"了解、學習應用程序的手段。因為單元測試程序就是應用程序的"客戶",所以無論它是事先寫的,還是事后寫的,都可以很好地表現出應用程序的行為。
4. 事后單元測試,也可能轉化為事先單元測試。在應用程序的整個生命周期中,維護階段是最長的。在"漫長"的維護過程中,"之前"所寫的"事后"單元測試將會成為"后來者"(包括原始作者本人)的"事先"單元測試。在改進程序的過程中,這些單元測試仍然能起到監督的作用。(orz,有點兒詭辯)
雖然,事后單元測試明顯不如事先單元測試,但它的作用仍然不可低估。只要編寫了優秀的單元測試程序,無論是在哪個階段,它都會對改進應用程序有莫大的幫助。(這可不是"聊勝于無"能夠表達的)
延伸閱讀
文章來源于領測軟件測試網 http://www.kjueaiud.com/