实施TDD时的常见问题
在InfoQ發表的一篇文章《實施TDD時的常見問題》中, Chad Meyers提出了關于TDD實施的問題,如下所示:
Derick Bailey分享了他對Chad這些問題的看法。以下是他的回答的摘錄:
這個問題實際上應該根據你的實際項目來回答。我最近做了一個企業集成項目,里面用到了我們的核心維護系統,然后添加了一些離線操作功能。在這個項目中,我 沒有做太多的預先設計。我知道系統需要能夠在離線模式下操作,我還知道即使是沒人登錄計算機或者運行這個軟件時,它也需要能夠執行一些操作,我知道它需要 跟主維護系統進行雙向通信,用來執行與維護相關的的一定數量的任務。我從一些設想/預先設計開始動手——構建了一個Windows Service來運行核心進程,構建了一個客戶端-服務器架構來托管UI,在一個消息系統上為通信提供支持。除了這些算是預先設計以外,在構建軟件的過程 中都是其他各項任務的功能需求來驅動項目設計的進展。
最近,我與一個為實驗室開發某系統的團隊一起工作時,有了截然相反的體驗。我們有源于客戶的需求,客戶所要求的流程,以及對客戶手中數據進行轉換的需要; 我們需要一個大規模的預先設計,用以判斷我們的解決方案可以滿足數據轉換和功能需求。系統的核心設計是預先完成的,但是具體實現還是在開發過程中慢慢成 型。
你應該只添加你需要的方法。如果你擁有一個真實的對象,它包含了將要拋出的未實現的異常,你可能要檢查一下這個方法,看它是否能夠從代碼庫中刪除。
我花了很多時間和我的合作者開展結對編程。我們不斷遇到這樣一個場景,即下一個功能需求會導致現有設計的改變。如果發生了這樣的事情,我們只會對我們需要的 部分進行修改。我們會為某些新功能編寫新的單元測試,如果之前的設計使得我們的單元測試無法通過,我們就會返回修改之前的設計——對在修改范圍內的單元測 試進行修改與更新。我們要將在這種情況之下的單元測試看作是“必做列表”中的內容。當我們修改已經完成的設計時,我們通常會忘記這個已經修改的范圍,或者 忘記我們試圖滿足的新的功能需求。所幸,通過對整個單元測試套件的完整運行,可以顯示被破壞的測試,提醒我們需要修改。
在結對編程期間,我們有很多機會獲得新的需求,回顧我們的設計與實現,通過對這一特定需求的理解,認識到整個模型是錯誤的,我們需要從頭編寫。此時,我們做了 許多人想都沒有想過的事情——我們刪除了系統中的所有類和單元測試,然后從頭再來。通過這種方法獲得的經驗教訓以及對其他需求的理解,可以引導我們開始一 個新的設計,它能夠考慮我們需要的功能——但是,我們仍然能夠在我們需要的基礎上,編寫現有的功能。我們雖然沒有創建“未來的代碼”,但通過額外的接口和 抽象提供了可擴展性……
我已經反復強調了這樣一個循環:“設計、修改、重新設計、修改、重新開始構建、修改”。根據我的經驗,最終的結果值得我們這樣去做——系統中更少的bug,更加準確地表示業務需求的模型,更好的擴展性和靈活性,從而允許在未來作出修改。
此外, Derick Bailey還談到了其他有關TDD的問題,例如對斷言的比較,對SetUp方法的分析,對重構工具的認識等。
對于這7個問題,我的回答如下:
1、 預先設計的度并沒有一個準確的值。首先對于一個系統而言,我們應該從領域與架構的角度分析技術關鍵點,并對這些關鍵點進行預先設計,是非常有必要的。此 外,對于系統的infrastructure的內容,我們也需要預先設計,除非這些內容是已經存在的。其實,如果采用領域驅動設計的方式開展對領域邏輯的 分析,那么何時開始做測試,應該沒有太大的歧義,它自有一套規則需要我們遵循。TDD并不是完全排除設計的作用,利用測試來驅動開發,其實同時也代表我們 可以利用測試來驅動設計。因此,我的意見是如果將系統各個組成部分看作是package或者component,那么理想地TDD起點應該是在 package或component被劃分好之后,我們就可以利用單元測試來驅動我們對領域模型的思考與編碼實現了。
2、這個問題沒有什么好說。如果是問題中的例子,我想沒有什么好爭論的,正如Derick Bailey所說,我們確實不會對Main方法進行單元測試。我贊成Derick的意見。
3、 顯然,如果能夠利用工具來模擬樁對象,何樂而不為?如果測試代碼依賴的接口和實體類,本身就是我們在實現系統時就需要的,那么實現它們算不上是無用功,此 時,我贊成先去定義或者實現它們。不過在定義和實現它們的同時,需要考慮到這些定義不一定完整與準確,我們還要考慮隨時會對其進行修改,修改后,還要必須 檢驗你的測試代碼。
4、既然發現有問題,為什么要暫時放過,以觀后效呢?我的思想一貫都是要將錯誤扼殺在搖籃中。否則,因為一時偷懶放過的這個問題,往往會在后面給我們帶來無窮無盡的煩惱。如果你不能確認這些錯誤,拿出來討論是一個比較好的辦法。
5、與問題4相似。
6、 具體看修改的范圍。如果測試需要修改的不會影響依賴它的測試用例,即不會修改它的外部接口,那么只需要修改部分實現代碼就可以了。沒有必要去專門編寫一個 新的測試用例。如果涉及到對外部接口的需要,可以考慮重構。例如Derick提到的重命名的問題。如果重構不能解決,那就可以編寫一個新的測試。
7、很顯然,與問題4相同。
?
轉載于:https://blog.51cto.com/wayfarer/280173
總結
以上是生活随笔為你收集整理的实施TDD时的常见问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: FFT算法实现
- 下一篇: 《Leadership and the