2008-10-03 76 views
6

我被要求寫需要測試基於數據庫中多行一個新的存儲過程的測試應用程序運行多個斷言,在本質上我想要做這樣的事情:NUnit的:在一個測試

 

[Test] 
public void TestSelect() 
{ 
    foreach(id in ids) 
    { 
     DataTable old = Database.call("old_stored_proc",id); 
     DataTable new_ = Database.call("new_stored_proc",id); 

     Assert.AreEqual(old.Rows[0]["column"],ne_.Rows[0]["column"]); 
    } 
} 
 

當我運行這個測試時,如果1行不匹配另一個,整個測試失敗;相反,我想指出斷言通過了多少次,失敗了多少次。有沒有辦法用NUnit來做到這一點?

我意識到,NUnit可能是矯枉過正,這是一個沒有它的簡單任務...我只是想了解它。 ;)

回答

5

1)如果ID是恆定的,而不是在試運行時擡頭,爲每個ID創建一個單獨的單元測試夾具。這樣你就會知道哪個ID實際上是失敗的。在這裏看到的寫了與數據驅動測試的問題:
http://googletesting.blogspot.com/2008/09/tott-data-driven-traps.html

2)如果您需要動態查找該ID的,根本不可能爲每個ID的夾具,使用akmad的一個變化建議。保留值不相等的id列表並將該列表添加到錯誤消息中。要診斷一個失敗的測試是非常困難的,只能說明錯誤的數量,因爲您不知道錯誤的原因是什麼。 3)我不知道在NUnit中做什麼是困難的,但是在PyUnit中,當我們需要在動態生成的數據上運行測試時,我們動態地創建測試fixtures並將它們附加到TestCase類,以便對於沒有通過的每一條數據,我們都有一個失敗的測試。儘管我想如果沒有python的動態能力,這會變得更加困難。

+0

謝謝,我真正在尋找的是你的#3 ...但是就像你說的...這是.net :( – mmattax 2008-10-03 21:04:46

0

那麼你可以聲明一個計數器,然後斷言計數器的值,以確定合格/不合格

另外,你可以做大量的測試設置工作,然後就創建多個測試。

我不清楚爲什麼你需要在同一個測試中的所有assert stmts。

+0

我想聲明該存儲過程適用於數據庫中的每一行。 – mmattax 2008-10-03 16:03:01

1

我會計算不匹配的行數,然後會寫一個斷言,它會將此數字與0進行比較,並返回消息中不匹配字符串的數量。

你也可以使用Assert.Greater這個。

P.S.原則上你應該試着做一個單元測試的斷言。這是它的要點。

9

看起來像你只是斷言錯誤的東西。如果要檢查所有的值,然後斷言,沒有任何錯誤(或顯示錯誤的數量),那麼試試這個:

[Test] 
public void TestSelect() 
{ 
    int errors = 0; 
    foreach(id in ids) 
    { 
     DataTable old = Database.call("old_stored_proc",id); 
     DataTable new_ = Database.call("new_stored_proc",id); 

     if (old.Rows[0]["column"] != new_.Rows[0]["column"]) 
     { 
      errors++; 
     }    
    } 

    Assert.AreEqual(0, errors, "There were " + errors + " errors."); 
} 
0

根據您制定的目標,如果一行不匹配另一行,則整個測試應該失敗。通過計算斷言通過或失敗的次數,可以比根據您預期的結果與實際得到的結果進行比較,獲得更少的信息。

4

我知道這個問題特別關於NUnit,但有趣的是,Gallio/MbUnit有一個功能,它允許一次運行並捕獲多個斷言。

[Test] 
public void MultipleTest() 
{ 
    Assert.Multiple(() => 
    { 
     Assert.IsTrue(blabla); 
     Assert.AreEqual(pik, pok); 
     // etc. 
    } 
} 

Assert.Multiple正趕上所有失敗的斷言,並打算在測試結束時報告它們。

0

我最近有同樣的問題。我結合計數與Assert.Multiple的晏Trevin的提及錯誤轉化爲IEnumberable的擴展方法,讓我不喜歡的東西的想法:

[Test] 
public void TestEvenNumbers() 
{ 
    int[] numbers = new int[] { 2, 4, 12, 22, 13, 42 }; 
    numbers.AssertAll((num) => Assert.That((num % 2) == 0, "{0} is an odd number", num)); 
} 

導致NUnit的輸出:

TestEvenNumbers: 
    5 of 6 tests passed; 0 inconclusive 
FAILED: 13: 13 is an odd number 
    Expected: True 
    But was: False 

    Expected: 6 
    But was: 5 

而且該解決方案業務方案的問題是:

[Test] 
public void TestSelect() 
{ 
    ids.AssertAll(CheckStoredProcedures); 
} 

private void CheckStoredProcedures(Id id) 
{ 
    DataTable old = Database.call("old_stored_proc",id); 
    DataTable new_ = Database.call("new_stored_proc",id); 

    Assert.AreEqual(old.Rows[0]["column"], new_.Rows[0]["column"]); 
} 

這裏是(我用的,而不是「多」的一致性與LINQ的術語「全部」注​​)的擴展方法:

using System; 
using System.Text; 
using System.Collections.Generic; 
using NUnit.Framework; 

public static class NUnitExtensions 
{ 
    public static void AssertAll<T>(this IEnumerable<T> objects, Action<T> test) 
    { 
     int total = 0; 
     int passed = 0; 
     int failed = 0; 
     int inconclusive = 0; 
     var sb = new StringBuilder(); 
     foreach (var obj in objects) 
     { 
      total++; 
      try 
      { 
       test(obj); 
       passed++; 
      } 
      catch (InconclusiveException assertion) 
      { 
       inconclusive++; 
       string message = string.Format("INCONCLUSIVE: {0}: {1}", obj.ToString(), assertion.Message); 
       Console.WriteLine(message); 
       sb.AppendLine(message); 
      } 
      catch (AssertionException assertion) 
      { 
       failed++; 
       string message = string.Format("FAILED: {0}: {1}", obj.ToString(), assertion.Message); 
       Console.WriteLine(message); 
       sb.AppendLine(message); 
      } 
     } 

     if (passed != total) 
     { 
      string details = sb.ToString(); 
      string message = string.Format("{0} of {1} tests passed; {2} inconclusive\n{3}", passed, total, inconclusive, details); 
      if (failed == 0) 
      { 
       Assert.Inconclusive(message); 
      } 
      else 
      { 
       Assert.AreEqual(total, passed, message); 
      } 
     } 
    } 
}