在 NUnit 中比较文本文件的单元测试

问题描述 投票:0回答:6

我有一个处理 2 个 xml 文件并生成一个文本文件的类。

我想编写一堆单元/集成测试,这些测试可以针对此类执行以下操作单独通过或失败:

  1. 对于输入A和B,生成输出。
  2. 将生成文件的内容与预期输出的内容进行比较
  3. 当实际内容与预期内容不同时,失败并显示一些有关差异的有用信息。

下面是课程的原型以及我第一次尝试单元测试。

是否有我应该用于此类测试的模式,或者人们倾向于编写无数的 TestX() 函数?

是否有更好的方法来从 NUnit 中提取文本文件差异? 我应该嵌入文本文件差异算法吗?


class ReportGenerator
{
    string Generate(string inputPathA, string inputPathB)
    {
        //do stuff
    }
}

[TextFixture]
public class ReportGeneratorTests
{
     static Diff(string pathToExpectedResult, string pathToActualResult)
     {
         using (StreamReader rs1 = File.OpenText(pathToExpectedResult))
         {
             using (StreamReader rs2 = File.OpenText(pathToActualResult))
             {
                 string actualContents = rs2.ReadToEnd();
                 string expectedContents = rs1.ReadToEnd();                  

                 //this works, but the output could be a LOT more useful.
                 Assert.AreEqual(expectedContents, actualContents);
             }
         }
     }

     static TestGenerate(string pathToInputA, string pathToInputB, string pathToExpectedResult)
     {
          ReportGenerator obj = new ReportGenerator();
          string pathToResult = obj.Generate(pathToInputA, pathToInputB);
          Diff(pathToExpectedResult, pathToResult);
     }

     [Test]
     public void TestX()
     {
          TestGenerate("x1.xml", "x2.xml", "x-expected.txt");
     }

     [Test]
     public void TestY()
     {
          TestGenerate("y1.xml", "y2.xml", "y-expected.txt");
     }

     //etc...
}

更新

我对测试 diff 功能不感兴趣。我只是想用它来产生更具可读性的故障。

unit-testing nunit diff text-files
6个回答
5
投票

对于不同数据的多个测试,使用NUnit RowTest扩展:

using NUnit.Framework.Extensions;

[RowTest]
[Row("x1.xml", "x2.xml", "x-expected.xml")]
[Row("y1.xml", "y2.xml", "y-expected.xml")]
public void TestGenerate(string pathToInputA, string pathToInputB, string pathToExpectedResult)
 {
      ReportGenerator obj = new ReportGenerator();
      string pathToResult = obj.Generate(pathToInputA, pathToInputB);
      Diff(pathToExpectedResult, pathToResult);
 }

2
投票

您可能要求针对“黄金”数据进行测试。我不知道这种测试是否有特定的术语在世界范围内被接受,但我们就是这样做的。

创建基夹具类。它基本上有“void DoTest(string fileName)”,它将特定文件读入内存,执行抽象转换方法“string Transform(string text)”,然后从同一个地方读取 fileName.gold 并将转换后的文本与预期的进行比较.如果内容不同,则抛出异常。抛出的异常包含第一个差异的行号以及预期行和实际行的文本。由于文本是稳定的,这通常足以立即发现问题。请务必用“预期:”和“实际:”标记行,否则在查看测试结果时您将永远猜测哪个是哪个。

然后,您将拥有特定的测试装置,您可以在其中实现正确工作的 Transform 方法,然后进行如下所示的测试:

[Test] public void TestX() { DoTest("X"); }
[Test] public void TestY() { DoTest("Y"); }

失败测试的名称会立即告诉你什么坏了。当然,您可以使用行测试来对相似的测试进行分组。进行单独的测试在许多情况下也有帮助,例如忽略测试、与同事交流测试等。创建一个将在一秒钟内为您创建测试的代码段没什么大不了的,您将花费更多时间准备数据。

然后你还需要一些测试数据和你的基础夹具找到它的方式,一定要为项目设置关于它的规则。如果测试失败,将实际输出转储到 gold 附近的文件中,如果测试通过则将其擦除。这样您就可以在需要时使用 diff 工具。当没有找到 gold 数据时,测试失败并显示适当的消息,但实际输出无论如何都会被写入,因此您可以检查它是否正确并将其复制为“gold”。


0
投票

我可能会编写一个包含循环的单元测试。在循环中,我读取了 2 个 xml 文件和一个 diff 文件,然后比较 xml 文件(不将其写入磁盘)并将其与从磁盘读取的 diff 文件进行比较。这些文件将被编号,例如a1.xml, b1.xml, diff1.txt ; a2.xml, b2.xml, diff2.txt ; a3.xml、b3.xml、diff3.txt等,找不到下一个数字就停止循环

然后,你可以通过添加新的文本文件来编写新的测试。


0
投票

您可以自己解析两个输入流,而不是调用 .AreEqual,计算行和列的数量并比较内容。一旦发现差异,您就可以生成一条消息,例如...

第 32 行第 12 列 - 在预期为“y”时找到了“x”

您可以选择通过显示多行输出来增强它

第 32 行第 12 列的差异,显示第一个差异
A = 这是一个 txst
B = 这是一个 tests

注意,通常,我通常只会通过我的代码生成您拥有的两个流之一。另一个我从测试/文本文件中获取,通过眼睛或其他方法验证包含的数据是正确的!


0
投票

我可能会使用 XmlReader 遍历文件并比较它们。当我遇到差异时,我会显示一个指向文件不同位置的 XPath。

PS:但实际上,我只需将整个文件简单地读取为一个字符串并比较这两个字符串就足够了。对于报告来说,看到测试失败就足够了。然后,当我进行调试时,我通常使用 Araxis Merge 比较文件,以查看我到底在哪里有问题。


-1
投票

Это ещё разsdfsadgfsfdasaf dsgfdsfgdsfgdsfhdfshgтредактированный тестовый ответ。 Пожалуйста, не баньте

© www.soinside.com 2019 - 2024. All rights reserved.