' returns the sum of the two numbers Function Sum(ByVal a As Integer, ByVal b As Integer) As Integer |
你可以向如下的方式寫一個失敗測試
<TestMethod()> _ Public Sub Sum_AddsOneAndTwo() Dim result As Integer = Sum(1, 2) Assert.AreEqual(4, result, "bad sum"); End Sub |
初看上去這個處理像是一個寫失敗測試的好的方法,它完全錯失了你寫錯誤測試的初始點。
一個失敗測試驗證了在代碼中存在一些錯誤,當你的測試完成后這個測試應該是通過的,現在的例子中,無論如何,測試都將會失敗,即使是代碼完成,因為測試邏輯上不是正確的。如果希望測試通過測需要測試自身進行修改――而不是程序的代碼的改變(當程序代碼改變的時候,是test-first規劃的意圖)簡短來說,這個測試不會反映出程序代碼完成后的最終的結果,因此這個不是一個好的測試。
TDD中一個好的測試要求你去修改代碼,從而使它能夠按照想要的方式工作,這一點要勝于強迫你去反映現在的真實情況或者一個非邏輯要求的渴望的結果。例如,當1+1返回0時就意味著測試失敗。這個簡單的例子和這種情況是相似的,在練習中,如果現在的需求是在工作的,測試應該可以反映你所期待的結果,然后你可以調整現在代碼的情況去通過這個測試。
作為一個規則,一個已經調通的測試不應該被移除掉,因為這個測試在維護工作中可以用于恢復測試。他們在你改變代碼時用來確定你沒有損害到現在已經工作的函數。這就是為什么你不應該修改那些已經通過的測試,除非是一些很小的修改,例如增加它的可讀性(換句話說,分解測試)
當一個測試非正常失敗 有時你可能遇到失敗的測試,而這時你對代碼的改變是完全合理的。這通常是因為你遇到了沖突的需求。一般來說,可能是一個新的需求(一個改變的特性)與一個舊的可能已經不再有效的需求發生了沖突。這有兩種可能:
1.在舊的需求或者無效或者在別處測試的情況下刪除被驗證本質上不再有效的失敗的測試
2.改變舊的測試使你可以測試新的要求(本質上使用新的測試),然后在新的設置下(測試的邏輯狀態相同,但是初始功能函數可能有所不同)測試舊的需求。
而有時候一個測試在使用不完整的技術去完成任務的時候也是有效的,例如,你有一個成員類帶有一個FOO方法,它表現為某幾種行為,它已經經由Test 在X年前測試完成,然后現在一些其他的需求加了進來,方法的邏輯增強了,從而可以去處理一些類似于在獲取數據時丟失一些參數的異常處理。但這時,突然 Test X失敗了,雖然在測試這個函數的時候只是使用了同樣的類。這個測試的失敗是因為在調用方法之前丟失了一些初始處理步驟。
這并不意味著你需要移除Test X,你將丟失對于一些重要功能的測試,這時你應該去關心那些初始化時的問題,而不是改變類的創建以用來適應你新的意圖。
當然如果你那里有200個測試都是因為舊的結構導致的失敗,你就應該找到這個問題來維護你的測試。這就是為什么你應該總是移除你測試中的副本尤其是在生產代碼中。
測試覆蓋和測試Angles 你如何知道是否你的新代碼是一個好的覆蓋?當試圖移動一個鏈接或者一個約束檢查后,如果所有的測試依然通過,那么你就沒有足夠的代碼復制然后你可能需要添加其他的測試單元。
確認你添加正確測試的最好方法就是測試一些最平常的行和檢查直到用非常的手段使它出錯。這個也許很難,但是如果你不能考慮出一個讓代碼出錯的方法,你就可能沒有好的理由在最初的地方寫下這行代碼。
你不知道什么時候下一個開發者會試圖運行你的程序,他可能優化或者錯誤的刪除一些包含本質的行。如果你沒有一個測試,它就會失敗,其他的開發者可能不會知道他們犯了錯誤。
你也可能試圖利用一些常量去替代一些已經通過了的測試中調用的各種各樣的參數,例如,看下面的方法:
Public Function Sum(ByVal x As Integer, ByVal y As Integer, _ ByVal allowNegatives As Boolean) As Integer If Not allowNegatives Then Throw New Exception() Return x + y End Function |
原文轉自:http://www.uml.org.cn/Test/200605091.htm