2010-07-23 101 views
7

我正在處理一些測試用例,我經常發現在每種情況下都會出現多個斷言。例如(過於簡化和剝離爲了簡潔評論):如何防止測試用例中的「過度測試」? (C#/ nUnit)

[Test] 
public void TestNamePropertyCorrectlySetOnInstantiation() 
{ 
    MyClass myInstance = new MyClass("Test name"); 
    Assert.AreEqual("Test Name", myInstance.Name); 
} 

這看起來原則上可以接受,但測試的重點是驗證,當類被實例化一個給定的名稱,名稱屬性設置正確,但如果在實例化過程中出現任何錯誤,它甚至會在斷言之前失敗。

我重構這樣的:

[Test] 
public void TestNamePropertyCorrectlySetOnInstantiation() 
{ 
    MyClass myInstance; 
    string namePropertyValue; 

    Assert.DoesNotThrow(() => myInstance = new MyClass("Test name")); 
    Assert.DoesNotThrow(() => namePropertyValue = myInstance.Name); 
    Assert.AreEqual("Test Name", namePropertyValue); 
} 

但當然,現在我居然在這裏測試的三件事;在這個測試中,我沒有興趣測試MyClass的實例是否成功實例化,或者名稱屬性是否成功讀取,這些測試是在另一種情況下進行的。但是,如果前兩個測試失敗了,甚至不可能進行測試,那麼我怎樣才能測試最後一個斷言而不先斷言另外兩個斷言?

回答

12

只是有其他的測試,如果你以一種無效的方式初始化它,它會檢查是否有異常。 IMO的第一種形式很好。

就我個人而言,我會避免掛上「每次測試一個斷言」的教條。嘗試通過代碼測試一個邏輯路徑,以達到實際意義上的精細粒度。

+0

沒錯,它並沒有太多關於堅持'一個斷言每個測試'的事情,雖然沒有看到一個紅色的blob對測試代碼時,它實際上測試工作正常。 – Flynn1179 2010-07-23 09:32:45

+0

@ Flynn1179:你爲什麼得到一個紅色的斑點?我不明白你的意思。 – 2010-07-23 09:36:10

+0

對不起,我忘了提及;我使用ReSharper運行nUnit測試,當測試失敗時,它在測試列表中顯示爲紅色斑點。由於在我測試的實際聲明之前發現了一個錯誤,因此我有很多測試「失敗」。 – Flynn1179 2010-07-23 09:44:40

0

在您的特定示例中,如果測試執行的一部分不存在,則不需要斷言某些東西不會拋出。這個方面已經在你的第一個測試中被測試過了,它更可讀。如果構造函數或屬性getter拋出異常,NUnit將通過相應的錯誤消息使測試失敗。 TBH我不確定Assert.DoesNotThrow()背後的想法是什麼,因爲如果你忽略它,你會得到幾乎相同的結果 - 但絕對不應該將它用作正常測試執行的一部分。將異常作爲語言的一部分的重點在於,您無需在每行代碼後檢查錯誤。

+0

是的,我認爲這可能不是最好的例子..一般來說,有一些測試需要一些特定於該測試的「設置」,但與您正在測試的功能不直接相關。我正在研究'Assert.Inconclusive',也許將'setup'包裝在try/catch中,如果它失敗,斷言不成立,但這會讓我的代碼更不可讀。 – Flynn1179 2010-07-23 13:53:31

0

Grzenio在這是正確的。如果拋出異常,第一個最簡單的示例測試將失敗 - 不需要明確測試該示例。

但是,您應該測試當無效數據傳遞給它時引發的異常

[Test] 
public void TestInvalidNameThrowsException { 
    MyClass myInstance; 
    string namePropertyValue; 
    Assert.Throws(() => myInstance = new MyClass(null)); 
    Assert.Throws(() => myInstance = new MyClass("INVALID_NAME_125356232356")); 
} 

(例如,我不知道C#的一位。但是,你應該明白我的意思。)

1

我真的不明白你是什麼意味着過測試海事組織,過度測試就像試圖測試私人方法。

我把我的測試作爲代碼的文檔。因此,如果我在聲明中有多個斷言,那麼我很可能會將測試方法重構爲幾個較小的方法,或者有時將我的測試方法拆分爲幾種不同的測試方法。遵循one-assert-per-test規則允許您擁有合理的測試方法名稱,這反過來形成您的代碼的文檔。我遵循的測試方法的命名約定是methodName_scenario_expectation(來自RoyOsherove的Art of Unit Testing)。所以,也從代碼的文檔來考慮。那麼,你認爲有一個斷言意志(除了驗證期望),可以幫助你/其他開發人員更好地理解代碼,然後繼續寫下這個斷言。但是,爲了重申一遍,那麼一定要確保你有正確的測試方法名稱。

+0

通過'過度測試',我正在談論測試用例何時'測試'功能而非其意圖,作爲設置預期測試的必要結果。 – Flynn1179 2010-07-23 15:04:19