2008-10-03 95 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); 
      } 
     } 
    } 
}