NUnit: запуск нескольких утверждений в одном тесте - PullRequest
6 голосов
/ 03 октября 2008

Меня попросили написать тестовое приложение, которое должно тестировать новую хранимую процедуру в нескольких строках базы данных, по сути, я хочу сделать что-то вроде этого:


[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"]);
    }
}

Когда я запускаю этот тест, если одна строка не совпадает с другой, весь тест не пройден; вместо этого я хотел бы посчитать, сколько раз утверждение было пройдено и сколько раз оно провалилось. Есть ли способ сделать это с NUnit?

Я понимаю, что NUnit может быть излишним, и это простое задание без него ... Я просто хотел изучить это. ;)

Ответы [ 8 ]

9 голосов
/ 03 октября 2008

Похоже, вы просто утверждаете не то. Если вы хотите проверить все значения и затем подтвердить, что ошибок нет (или показать количество ошибок), попробуйте следующее:

[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.");
}
5 голосов
/ 03 октября 2008

1) Если идентификаторы постоянны и не проверяются во время выполнения теста, создайте отдельное устройство для модульного тестирования для каждого идентификатора. Таким образом, вы будете знать, какие идентификаторы действительно не работают. Смотрите здесь для описания проблем с тестами на основе данных:
http://googletesting.blogspot.com/2008/09/tott-data-driven-traps.html

2) Если вам нужно динамически искать идентификатор, делающий невозможным создание прибора для каждого идентификатора, используйте предложение Акмада с одним изменением. Сохраните список идентификаторов, где значения не равны, и добавьте этот список в сообщение об ошибке. Диагностировать провальный тест, в котором будет указано только количество ошибок, будет крайне сложно, так как вы не будете знать, какие идентификаторы являются причиной ошибок.

3) Я не знаю, насколько сложно было бы это сделать в NUnit, но в PyUnit, когда нам нужно запустить тесты на динамически генерируемых данных, мы динамически создаем тестовые фикстуры и присоединяем их к классу TestCase, чтобы иметь неудачный тест для каждого фрагмента данных, который не проходит. Хотя я представляю, что это было бы намного сложнее без динамических способностей питона.

4 голосов
/ 28 мая 2010

Я знаю, что вопрос касается именно NUnit, но, что интересно, Gallio / MbUnit имеет функцию, которая позволяет запускать и перехватывать несколько утверждений одновременно.

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

Assert.Multiple перехватывает все ошибочных утверждений и собирается сообщить о них в конце теста.

1 голос
/ 03 октября 2008

Я бы посчитал количество строк, которые не совпадают, а затем написал бы утверждение, которое сравнило бы это число с 0 и вернуло бы количество несовпадающих строк в сообщении.

вы также можете использовать Assert.Greater для этого.

P.S. В принципе, вы должны попытаться сделать одно утверждение на единицу теста. В этом суть.

0 голосов
/ 20 июня 2018

Вы можете использовать [TestCase()] атрибут , если просто жестко закодировать список идентификаторов.

[Test]
[TestCase(1234)]
[TestCase(5678)]
[TestCase(7654)]
public void TestSelect(int 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"]);
}

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

Если необходимо сгенерировать динамический список идентификаторов, рекомендуем использовать атрибут [TestCaseSource()] .

0 голосов
/ 09 мая 2014

У меня недавно была такая же проблема. Я объединил идею подсчета ошибок с упоминанием Яна Тревина об Assert.Multiple в метод расширения для 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"]);
}

Вот метод расширения (обратите внимание, что я использовал «All» вместо «Multiple» для соответствия терминологии 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);
            }
        }
    }
}
0 голосов
/ 09 октября 2008

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

0 голосов
/ 03 октября 2008

Ну, вы могли бы объявить счетчик, а затем установить значение счетчика, чтобы определить, прошел / не прошел

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

Мне не ясно, зачем вам все stmts assert в одном и том же тесте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...