Модульные тесты для сравнения текстовых файлов в NUnit - PullRequest
5 голосов
/ 27 сентября 2008

У меня есть класс, который обрабатывает 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...
}

Обновление

Я не заинтересован в тестировании различий. Я просто хочу использовать его для создания более читаемых сбоев.

Ответы [ 5 ]

5 голосов
/ 27 сентября 2008

Что касается нескольких тестов с разными данными, используйте расширение 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 голосов
/ 28 сентября 2008

Вы, вероятно, запрашиваете тестирование на «золотых» данных. Я не знаю, существует ли конкретный термин для такого рода испытаний, принятый во всем мире, но именно так мы это делаем.

Создать базовый класс приборов. Он в основном имеет «void DoTest (string fileName)», который будет считывать конкретный файл в память, выполнять абстрактный метод преобразования «string Transform (string text)», затем считывать fileName.gold из того же места и сравнивать преобразованный текст с ожидаемым , Если содержимое отличается, оно выдает исключение. Исключенное исключение содержит номер строки первого различия, а также текст ожидаемой и фактической строки. Поскольку текст стабилен, обычно этой информации достаточно, чтобы сразу определить проблему. Обязательно пометьте строки «Expected:» и «Actual:», иначе вы будете угадывать, что есть, когда смотрите на результаты теста.

Затем у вас будут специальные тестовые таблицы, в которых вы реализуете метод Transform, который делает правильную работу, а затем у вас будут тесты, которые выглядят так:

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

Имя неудачного теста мгновенно скажет вам, что сломано. Конечно, вы можете использовать тестирование строк для группировки похожих тестов. Наличие отдельных тестов также помогает в ряде ситуаций, таких как игнорирование тестов, передача тестов коллегам и так далее. Нет ничего сложного в том, чтобы создать фрагмент, который за секунду создаст для вас тест, вы потратите гораздо больше времени на подготовку данных.

Тогда вам также понадобятся некоторые тестовые данные и способ, которым ваш базовый прибор найдет их. Обязательно установите правила для этого проекта. Если тест не пройден, выведите фактический вывод в файл рядом с золотом и сотрите его, если тест пройден. Таким образом, вы можете использовать diff инструмент, когда это необходимо. Когда золотые данные не найдены, тест завершается неудачно с соответствующим сообщением, но фактический вывод записывается в любом случае, так что вы можете проверить его правильность и скопировать, чтобы он стал «золотым».

0 голосов
/ 27 сентября 2008

Я бы, вероятно, использовал XmlReader для перебора файлов и их сравнения. Когда я сталкиваюсь с разницей, я отображаю XPath к месту, где файлы отличаются.

PS: Но на самом деле мне всегда было достаточно просто прочитать весь файл в строку и сравнить две строки. Для отчетности достаточно убедиться, что тест не пройден. Затем, когда я выполняю отладку, я обычно проверяю файлы, используя Araxis Merge , чтобы увидеть, где именно у меня проблемы.

0 голосов
/ 27 сентября 2008

Я бы, наверное, написал один модульный тест, содержащий цикл. Внутри цикла я читал 2 xml-файла и diff-файл, а затем отправлял diff-файлы xml (без записи на диск) и сравнивал их с diff-файлом, считываемым с диска. Файлы будут пронумерованы, например, a1.xml, b1.xml, diff1.txt; a2.xml, b2.xml, diff2.txt; a3.xml, b3.xml, diff3.txt и т. д., и цикл останавливается, когда он не находит следующего числа.

Затем вы можете написать новые тесты, просто добавив новые текстовые файлы.

0 голосов
/ 27 сентября 2008

Вместо вызова .AreEqual вы можете самостоятельно проанализировать два входных потока, вести подсчет строки и столбца и сравнивать содержимое. Как только вы обнаружите разницу, вы можете сгенерировать сообщение вроде ...

Строка 32, столбец 12 - найдено «х», когда ожидалось «у»

При желании вы можете улучшить это, отображая несколько строк вывода

Разница в строке 32, столбец 12, показана первая разница
A = это т х ст
B = это т е сц

Обратите внимание, что, как правило, я обычно генерирую из своего кода только один из двух ваших потоков. Другой я бы взял из тестового / текстового файла, проверив на глаз или другим методом, что содержащиеся в нем данные верны!

...