2009-11-23 105 views
11

我正在爲數據庫操作編寫一些NUnit測試。顯然,如果Add()失敗,那麼Get()也會失敗。然而,當Add()Get()都失敗時,它看起來就像是在欺騙,因爲看起來有兩個問題,而不是一個。如何忽略基於NUnit中另一個測試的測試?

是否有一種方法可以指定要運行的測試的'順序',因爲如果第一次測試失敗,以下測試將被忽略?

在同一行中,有沒有一種方法來訂購單元測試類本身?例如,我想在用於從UI中往返數據的測試之前首先運行我的基本數據庫操作測試。

注意:這與測試相互依賴有點不同,它更像是確保某些東西在運行一堆測試之前先工作。例如,如果首先無法連接到數據庫,那麼運行一堆數據庫操作是浪費時間。

編輯:似乎有些人缺少重點。我不這樣做:

[Test] 
public void AddTest() 
{ 
    db.Add(someData); 
} 

[Test] 
public void GetTest() 
{ 
    db.Get(someData); 
    Assert.That(data was retrieved successfully); 
} 

相反,我這樣做:

[Test] 
public void AddTest() 
{ 
    db.Add(someData); 
} 

[Test] 
public void GetTest() 
{ 
    // need some way here to ensure that db.Add() can actually be performed successfully 
    db.Add(someData); 
    db.Get(somedata); 
    Assert.That(data was retrieved successfully); 
} 

換句話說,我要確保數據能夠在第一時間之前,我可以添加測試它是否可以被檢索。人們假設我使用第一次測試的數據來通過第二次測試,但情況並非如此。我試圖確保一個操作是可能之前嘗試另一個依賴於它。

正如我所說的,您需要確保您可以在運行數據庫操作之前獲得與數據庫的連接。或者你可以在執行文件操作之前打開一個文件。或者在測試API調用之前連接到服務器。或者......你明白了。

+1

接受的答案是**錯誤**!見評論 – Graviton 2009-11-24 10:03:30

回答

-3

創建一個全局變量,並在測試返回Get除非Add其設置爲true(在Add最後一行做到這一點):

public boolean addFailed = false; 
public void testAdd() { 
    try { 
     ... old test code ... 
    } catch (Throwable t) { // Catch all errors 
     addFailed = true; 
     throw t; // Don't forget to rethrow 
    } 
} 
public void testGet() { 
    if (addFailed) return; 
    ... old test code ... 
} 
+0

謝謝。這不是很優雅,但它看起來像NUnit本身不支持此功能。 – 2009-11-23 13:24:49

+1

你想要的是一個黑客,所以解決方案也是一個;) – 2009-11-23 13:47:58

+0

我不是這個解決方案的粉絲。 testGet方法沒有通過,它沒有運行。應該這樣報道。 – 2009-11-23 15:26:36

1

我不認爲這是可能的失框。

無論如何,您所描述的測試類設計會使測試代碼非常脆弱。

+0

我沒有運行'Add()'測試,先將數據添加到數據庫中,然後運行'Get()'測試來獲取數據。相反,我想確保'Add()'在Get()'測試之前首先工作,有點像說「好吧,我可以將數據添加到數據庫中嗎?好,現在添加這個測試數據,看看我能否檢索它。」 – 2009-11-23 12:55:59

0

MbUnit似乎有一個DependsOnAttribute,這將允許你做你想做的。

如果然後將另一測試夾具或測試 方法失敗此測試不會 運行。此外,依賴性力量 這個測試在那些依賴於它的人之後運行。

儘管對NUnit一無所知。

+0

謝謝,這正是我正在尋找的。如果我願意,我可以切換到MbUnit還很早,所以我會研究它。 – 2009-11-23 13:29:09

14

NUnit的支持用於驗證setup.This被記錄爲Theory(感謝clairestreb)的一部分的「Assume.That」語法。在NUnit.Framework命名空間是一個類Assume。引述文件:

/// Provides static methods to express the assumptions 
/// that must be met for a test to give a meaningful 
/// result. If an assumption is not met, the test 
/// should produce an inconclusive result. 

所以在背景:

public void TestGet() { 
    MyList sut = new MyList() 
    Object expecting = new Object(); 
    sut.Put(expecting); 
    Assume.That(sut.size(), Is(1)); 
    Assert.That(sut.Get(), Is(expecting)); 
} 
+2

這應該是被接受的答案,聲明依賴關係的極好方式,而「不確定」恰恰是正確的結果,在大多數測試框架中,結果都是橙色的:意思是還有一些事情需要完成。 – Abel 2013-01-03 23:20:17

+1

7年後,但我不斷回到這篇文章,所以這裏是文檔:http://nunit.org/index.php?p=theory&r=2.0 – clairestreb 2016-09-22 16:30:26

5

測試應該從未互相依賴。你剛剛發現了原因。根據定義,相互依賴的測試是脆弱的。如果您需要數據庫中的數據用於Get()的測試,請將其置於設置步驟中。

+0

除了它不脆弱。你錯過了這一點。在進行測試之前,您需要確保某些東西可用。在我的情況下,我需要確保'Add()'工作,因爲如果沒有它,'Get()'將不會獲得任何數據。無論它是否在設置中,因爲我在我的'Get()'測試中使用'Add()',但是我需要確保'Add()'在運行測試之前真正起作用。 – 2009-11-23 12:53:02

+4

這就是嘲笑和殘片。在對'Get()'的測試中,您應該能夠爲Get()提供虛擬數據,以便測試可以在沒有'Add()'的情況下運行。這可能意味着傳遞一個Add()的子類,它不會做任何可能導致它失敗的事情。關鍵是單元測試應該只測試有問題的單元。有沒有測試Get()而不測試Add()的方法。如果你得到了你所要求的修復,那麼如果Add()壞了,你就不知道'Get()'是否工作。這意味着你無法獲得系統的可靠快照。 – jcdyer 2009-11-23 15:42:40

+0

@Daniel T.你錯過了這一點。測試應始終獨立於對方。這意味着在'Get()'測試中使用'Add()'不是一個好主意。如果Add()中斷,Get()的測試也會中斷。你的測試不是孤立的。誰說你需要使用'Add()'來爲'Get()'準備你的數據庫...... – EricSchaefer 2009-11-23 18:01:47

2

我認爲問題在於你使用NUnit來運行NUnit運行的單元測試之外的其他東西。

本質上,您希望AddTest在GetTest之前運行,並且您希望NUnit在AddTest失敗時停止執行測試。

問題是,這是單元測試的對立面 - 測試應該是完全獨立的並且以任何順序運行。

單元測試的標準概念是,如果您對「添加」功能進行了測試,那麼您可以在「獲取」測試中使用「添加」功能,而不必擔心「添加」 '得到'測試。你知道'添加'的作品 - 你有一個測試。

'FIRST'原理(http://agileinaflash.blogspot.com/2009/02/first.html)描述了單元測試應如何表現。你想寫的測試違反'我'(孤立)和'R'(可重複)。

如果您擔心兩個測試之間的數據庫連接會斷開,我建議您在測試期間不要連接到真實的數據庫,您的代碼應該使用某種數據接口,並且對於測試,你應該使用模擬接口。如果測試點來執行數據庫連接,那麼您可能只是使用了錯誤的工具來完成這項工作 - 這不是真正的單元測試。

+0

你說的話有很大的意義,但是我仍然無法理解如何從'Add()'中分離'Get()'。我看到它的方式,就像有一個空盒子。在測試是否可以拿出來之前,你必須能夠在盒子內放入東西。 – 2009-11-23 19:47:34

+0

他們是儘可能孤立的。如果你想'Get()',你顯然需要首先在同一個測試中(或在設置中)放置()。隔離來自這樣的事實,即你的兩個測試正在測試完全不同的東西 - 你的第一個測試'Put()',你的第二個測試'Get()'。 如果'Put()'失敗,它們都會失敗 - 但沒關係。沒有單元測試規則說如果系統的某個區域出現故障,它應該中斷一個測試 - 它只需要至少打破一次測試,希望其中一個特別測試該區域。 – 2009-11-23 20:48:13

+0

我和一位同事聊了一會,他說盡管在理論上,防止級聯失敗會很好,但實際上級聯失敗實際上阻礙了任何事情的情況很少發生。換句話說,如果您有200多個測試,並且測試可以從數據庫中檢索數據是否失敗,那麼忽略其餘測試會很好,因爲它們也會自動失敗。但是因爲測試通常會很快運行,並且應該根據您正在測試的圖層進行分組,所以查看問題應該很容易。 – 2009-11-23 22:29:50

0

您不能假定測試夾具執行的任何順序,所以必須在您的測試類中檢查任何先決條件。

將您的添加測試分隔到一個測試類中,例如AddTests,並將Get測試放到另一個測試類中,例如類GetTests。

在GetTests類的[TestFixtureSetUp]方法中,如果您認爲合適,請檢查您是否有工作的數據庫訪問權限(例如,Add的工作),如果沒有,Assert.Ignore或Inconclusive。

當不滿足其前提條件時,將中止GetTests測試夾具,並跳過嘗試運行其包含的任何單元測試。 (我想!我是一個nUnit新手。)