2011-05-01 174 views
12

使用.NET 4.0代碼合同進行TDD的最佳做法建議是什麼?如何使用代碼合同進行單元測試

我想具體地說,我的問題是,鑑於TDD的一點是允許代碼自我記錄並且合同現在提供文檔的一部分,應該以與其他代碼相同的方式測試代碼合同?

回答

11

這取決於您如何使用合同以及您正在開發哪種應用程序。

首先:你當然不想separetly測試斷言和後置條件(Contract.AssertContract.AssumeContract.EnsuresContract.EnsuresOnThrow)。 我沒有看到這樣做的實際價值 - 因爲它們已經在重寫器的運行時期間得到驗證,即使沒有測試,您也會發現失敗非常快。
但是,在經過良好測試的應用程序中,即使在無效輸入上,後置條件或斷言也不會失敗。因此,如果你所有的測試(即使是測試無效數據處理的測試)都沒有一個後置條件/斷言失敗,你的後置條件和斷言可以被視爲「測試」。
爲此,您可能希望在測試中使用「Assert.Fail」處理ContractFailed事件。

現在「有趣」的部分是前提條件:
你正在開發一個庫嗎?那麼,如果你的時間/預算允許的話,你應該測試它們(它更糟糕的是不測試實際的邏輯)。
尤其是,如果您使用的是「Contract.Requires <E>」重載,它會在合同失敗時拋出特定異常,您應該像使用「if-throw」構造函數一樣對其進行常規參數驗證測試。

如果您不是在編寫庫,我不會說測試前置條件是非常必要的 - 它們不是真正的業務需求,而是調試的幫手。
如果一個參數爲null,那麼每寫一個單元測試可能會非常枯燥。
如果您在方法中忘記了此驗證碼(意思是:特定的Contract.Requires),那麼您也可能會忘記單元測試。因此,參數驗證測試爲您的(非庫)代碼帶來的附加值對連接值來說非常低。

總結:不測試後置條件和斷言。做測試前提條件 - 但僅限於庫(也可能是你的代碼庫的一部分)。

+0

「不要測試後置條件和斷言,測試前提條件 - 但僅限於庫(也可能是庫的一部分)。「 - 這聽起來像是相當不錯的建議:是基於你自己的經驗還是基於已經獲得的智慧? – briantyler 2011-05-01 20:36:39

+0

+1爲偉大的總結! – koenmetsu 2011-05-02 07:43:28

+0

@B泰勒:它基於我的經驗和與其他程序員的討論。然而,這仍然只是我的意見,並沒有任何研究或長期研究的支持;-) – Matthias 2011-05-02 14:23:30

1

偉大的問題。簡單回答是不。代碼合同可以處理與系統行爲無關的多餘測試。如果你真的可以達到100%的代碼覆蓋率,你將需要照顧isnull檢查等,這些檢查不需要在你的測試套件中。額外的好處是這些將在編譯時進行檢查,而不是等待測試執行。

希望這會有所幫助。

1

與代碼合同一起創建單元測試的有用工具是Pex。它分析你的代碼併爲它生成基本的單元測試。最重要的是它能夠識別和理解代碼合同,並對其生成的測試代碼進行調整。

如果您有MSDN訂閱,那麼您可以下載Pex/Moles作爲powertool,否則您可以在http://research.microsoft.com/en-us/projects/pex/downloads.aspx下載它(不是最新版本)。

3

我打算不同意這裏的其他人。合同不是測試,他們是關於API的要求和承諾的斷言。他們不會神奇地證明你的代碼是正確的,他們只是在違反合同時在運行時向你提供信息。我不知道你的情況,但是我討厭在某些特定情況下發送的代碼不符合合同並因合同斷言而崩潰!像任何其他行爲一樣,合同應該進行單元測試。如果您沒有運用合同(以及間接運用合同的代碼路徑),那麼您沒有證據證明代碼的有效性。代碼合同和單元測試不是相互排斥的概念。

+1

它們不是*只是*運行時信息;也可以執行導致編譯時錯誤的靜態驗證(例如,當使用可能爲空的參數調用方法時,但合同要求它不是)。 – TheXenocide 2014-11-13 21:58:43

0

測試在那裏測試代碼的行爲與預期

你不應該顯式地編寫測試行使合同斷言。

但是,在TDD或更改代碼時,運行單元測試可能會導致代碼失敗,導致合同失敗 - 如果發生這種情況,測試應該失敗,您希望能夠找到合同這很快且很容易失敗,因此您可以更正代碼。

所以不知爲何,你想趕上一個contractexception如果只是然後做Asser.Fail(「合同的要求沒有得到滿足」)

這可能是更多的你是什麼後 How to Log error while using Code Contracts