【问题标题】:Data-driven testing in NUnit?NUnit 中的数据驱动测试?
【发布时间】:2011-05-01 12:18:12
【问题描述】:

在 MSTest 中,您可以执行以下操作:

[TestMethod]
[DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", 
            "testdata.csv", "testdata#csv", DataAccessMethod.Sequential)]
public void TestSomething()
{
    double column1 = Convert.ToDouble(TestContext.DataRow["column1"]);
    ...
    Assert.AreEqual(...);
}

NUnit 2.5 中的等效代码是什么?

【问题讨论】:

    标签: c# .net-4.0 nunit nunit-2.5 data-driven-tests


    【解决方案1】:

    我在 NUnit 中进行了基于 csv 的数据驱动测试,工作如下:

    使用csv reader from code project,封装在测试类中返回 IEnumerable 的私有方法中,然后在测试用例中使用 TestCaseSource 属性引用它。在项目中包含您的 csv 文件并将“复制到输出目录”设置为“始终复制”

    using System.Collections.Generic;
    using System.IO;
    using LumenWorks.Framework.IO.Csv;
    using NUnit.Framework;
    
    namespace mytests
    {
        class MegaTests
        {
            [Test, TestCaseSource("GetTestData")]
            public void MyExample_Test(int data1, int data2, int expectedOutput)
            {
                var methodOutput = MethodUnderTest(data2, data1);
                Assert.AreEqual(expectedOutput, methodOutput, string.Format("Method failed for data1: {0}, data2: {1}", data1, data2));
            }
    
            private int MethodUnderTest(int data2, int data1)
            {
                return 42; //todo: real implementation
            }
    
            private IEnumerable<int[]> GetTestData()
            {
                using (var csv = new CsvReader(new StreamReader("test-data.csv"), true))
                {
                    while (csv.ReadNextRecord())
                    {
                        int data1 = int.Parse(csv[0]);
                        int data2 = int.Parse(csv[1]);
                        int expectedOutput = int.Parse(csv[2]);
                        yield return new[] { data1, data2, expectedOutput };
                    }
                }
            }
        }
    }
    

    原帖地址:http://timwise.blogspot.com/2011/05/data-driven-test-in-nunit-with-csv.html

    【讨论】:

      【解决方案2】:

      我会看看parameterized tests documentation in NUnit 2.5,看看你能不能做一些你正在做的事情。我不记得 NUnit 有一个内置的 CSV 读取属性来驱动参数化测试。不过可能在某个地方有一个社区插件。

      我还应该指出,如果您只是在寻找非 MS 单元测试框架库来帮助您,xUnit.net 确实具有此功能。看看这个blog post from Ben Hall

      【讨论】:

      • 谢谢 - 我已经做了一些挖掘工作。不存在这样的插件。也许我会自己做。我要求 NUnit 的主要原因是因为它是我唯一使用过的测试框架,仅此而已。
      • 试试 xUnit,如果它能让您在这方面的测试生活更轻松。它与 NUnit 非常相似(James Newkirk 开发了这两者!)并且它可以很容易地与 NUnit 一起存在,直到您确定是否要完全切换。我不建议将 xUnit 和 NUnit 作为您正在进行的解决方案的一部分,因为跑步者是不同的,我认为他们没有能力运行彼此的测试。
      【解决方案3】:

      这是另一个与 Tim Abell 非常相似的示例,但没有使用 CSV 阅读器框架并显示测试的细节。请注意,当您使用 TestCaseAttribute 时,可以省略 TestAttribute。

              [TestCaseSource("GetDataFromCSV")]
          public void TestDataFromCSV(int num1,int num2,int num3)
          {
              Assert.AreEqual(num1 + num2 ,num3);
          }
      
          private IEnumerable<int[]> GetDataFromCSV()
          {
              CsvReader reader = new CsvReader(path);
              while (reader.Next())
              {
                  int column1 = int.Parse(reader[0]);
                  int column2 = int.Parse(reader[1]);
                  int column3 = int.Parse(reader[2]);
                  yield return new int[] { column1, column2, column3 };
              }
          }
      
      
      public class CsvReader : IDisposable
      {
          private string path;
          private string[] currentData;
          private StreamReader reader;
      
          public CsvReader(string path)
          {
              if (!File.Exists(path)) throw new InvalidOperationException("path does not exist");
              this.path = path;
              Initialize();
          }
      
          private void Initialize()
          {
              FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read);
              reader = new StreamReader(stream);
          }
      
          public bool Next()
          {
              string current = null;
              if ((current = reader.ReadLine()) == null) return false;
              currentData = current.Split(',');
              return true;
          }
      
          public string this[int index]
          {
              get { return currentData[index]; }
          }
      
      
          public void Dispose()
          {
              reader.Close();
          }
      }
      

      CSV 数据:

      10,200,210 20,190,210 30,180,210 40,170,210 50,160,210 60,150,210 70,140,​​210 80,130,210 90,120,210 100,110,210

      注意:第 3 列是前两列的总和,这将在单元测试中断言。

      结果:

      在下面找到使用 TestCaseData 对象并设置返回类型的替代方法(这是强制性的)

              [TestCaseSource("GetDataFromCSV2")]
          public int TestDataFromCSV2(int num1, int num2)
          {
              return num1 + num2;
          }
      
          private IEnumerable GetDataFromCSV2()
          {
              CsvReader reader = new CsvReader(path);
              while (reader.Next())
              {
                  int column1 = int.Parse(reader[0]);
                  int column2 = int.Parse(reader[1]);
                  int column3 = int.Parse(reader[2]);
                  yield return new TestCaseData(column1, column2).Returns(column3);
              }
          }
      

      【讨论】:

        【解决方案4】:

        MS Test 提供了一种机制,可以让您的测试数据来自不同的来源。然而,这在 NUnit 中是不可用的。

        对于相当大的测试,我赞成将数据和代码分开。当我将两者分开时,我的期望是 1. 测试数据的可读性 2.测试数据要容易修改 3. 单元测试应该在本地和构建环境中舒适地运行

        下面的JsonSectionReader 具有我想要的所有功能。 该工具能够从嵌入式 json 文件中读取部分数据。它还提供了一种非常舒适的反序列化机制。

        https://www.nuget.org/packages/WonderTools.JsonSectionReader/

        附:我是这个项目的维护者,创建这个项目是因为我没有找到任何其他工具可以将这个问题解决到我想要的程度。

        【讨论】:

          【解决方案5】:

          我认为 Nunit 等价物是将一个方法标记为设置方法,然后将数据加载到一个字段中以供后续测试使用。

          你必须自己编写代码,或多或少。

          【讨论】:

            猜你喜欢
            • 2012-05-18
            • 1970-01-01
            • 2012-11-05
            • 2023-03-24
            • 1970-01-01
            • 1970-01-01
            • 2016-11-08
            • 2016-10-09
            • 1970-01-01
            相关资源
            最近更新 更多