2013-04-22 44 views
1

TDD最佳實踐表示新測試應該失敗。不過,我認爲有必要進行一次測試,儘管它剛剛寫入時不會失敗。編寫不首先失敗的測試

樣品的工作流程:

  1. 寫測試,檢查結束日期是否開始日期之前進入 - 測試失敗;
  2. 編寫代碼 - 測試通過;
bool Validate(Condition condition) 
{ 
    if (condition.EndDate <= condition.StartDate) 
    { 
     return false; 
    } 

    return true; 
} 

3.重構 - 測試仍然通過。

bool Validate(Condition condition) 
{ 
    return (condition.EndDate > condition.StartDate); 
} 

步驟3中我看到,如果我不是重構的條件後,我可以添加一個新的測試,檢查該方法,如果開始日期在結束日期之前返回true。但是,如果我先進行重構,那麼寫這樣的測試就意味着它會立即通過。對我來說,它看起來像測試可能會使代碼更健壯。

爲什麼要寫這樣的測試是一個壞主意/根據TDD不是一個好主意?

編輯:我現在在想,或許在實現中寫作return true;可能不是一個好主意,我應該拋出一個NotImplementedException。根據TDD編寫代碼是否是正確的方法?

回答

3

編寫一個失敗的測試的目的是讓每一個測試都是值得的。這只是讓你考慮你的測試和你的代碼。如果你編寫的測試不能開始,然後只有足夠的代碼來通過測試,那麼你知道你編碼的所有東西都是必須的,併爲你的應用程序增加了價值。例如,以最純粹的形式使用TDD,對於上述場景,如果您希望第一次測試測試方法是否在一個日期接近另一個時返回true,則可以編寫測試來聲明true和剛纔設置的方法

bool Validate(Condition condition) 
{ 
    return true; 
} 

這將使您的第一次測試通過。如果結束日期在開始日期之前,您將編寫另一個測試來斷言該方法是否失敗,這顯然會失敗。然後,您可以編寫代碼來通過測試,所以像:

bool Validate(Condition condition) 
{ 
    return (condition.EndDate > condition.StartDate); 
} 

這意味着你寫代碼的每一位有必要,你知道,當你希望它它的行爲完全。這也可以讓您將問題分解成幾個步驟,並逐個處理每個階段。據我瞭解,這就是TDD的全部內容。

+0

有關此問題的思考,我意識到,我違反寫作「剛剛夠」的原則,走了一步,沒有真正思考它。在我寫任何其他測試之前,'return true;'應該已經被單元測試覆蓋了。雖然這個例子已經完成,但我不止一次遇到過類似的問題。在編寫測試時,我會盡量多注意哪些代碼是正確的。我相信,在我的例子情況下,即使測試會通過,我還是應該把它寫,否則'返回true;'不包括在內。 – 2013-04-22 16:49:23

1

紅色/綠色/重構的想法是,當你編寫測試時,它不應該通過,因爲功能尚不存在。這是測試的要求,引導你編寫通過的實現。

您正在尋找一個非常簡單的案例。一位經驗豐富的TDD從業者可能會考慮這個問題並跳過測試執行步驟,直到編寫代碼後,節省編譯/測試周期的成本。

另一方面,可能會做更多的重構。有一件事是名稱:驗證。驗證什麼?它有什麼作用?它應該做多少?重命名它直到它說明它做了什麼。接下來,您正在對該對象外的對象進行日期比較。 「條件」類是否有責任確保結束日期在開始日期之後?或者它是否真的是一個商業規則,與條件的具體使用相關聯?

而且不要忘了更多的測試。你有什麼要求? StartDate可以爲空嗎?一個任務可能需要超過一天少,所以可以在結束日期和開始日期是一樣的嗎?但是,如果你比較分鐘和秒,也暗示這些真的是DateTime和不只是日期,而不應因此它們被命名的startDateTime/EndDateTime?

我們的目標不只是生產工作的軟件。目標是編寫可讀,可理解,清晰的軟件。該軟件應該作爲自己的文檔。 TDD可以通過提出正確的問題來幫助您。