Меня попросили написать приложение для тестирования, которое должно протестировать новую хранимую процедуру для нескольких строк в базе данных, по сути, я хочу сделать что-то вроде этого:
[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 может быть излишним, и без него это простая задача ... Я просто хотел изучить его. ;)





Ну, вы можете объявить счетчик, а затем подтвердить значение счетчика, чтобы определить годен / не годен
Кроме того, вы можете выполнить основную часть работы по настройке тестирования, а затем просто создать несколько тестов.
Я не понимаю, зачем вам нужны все утверждения assert в одном тесте.
Я бы посчитал количество строк, которые не совпадают, а затем написал бы утверждение, которое сравнит это число с 0 и вернет количество несовпадающих строк в сообщении.
вы также можете использовать для этого Assert.Greater.
P.S. В принципе, вы должны пытаться делать одно утверждение для каждого модульного теста. В этом суть.
Похоже, вы просто ошибаетесь. Если вы хотите проверить все значения, а затем подтвердить, что ошибок нет (или показать количество ошибок), попробуйте следующее:
[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.");
}
1) Если идентификаторы постоянны и не просматриваются во время выполнения теста, создайте отдельное приспособление для модульного теста для каждого идентификатора. Таким образом вы будете знать, какие идентификаторы на самом деле не работают. См. Здесь описание проблем с тестами на основе данных:
http://googletesting.blogspot.com/2008/09/tott-data-driven-traps.html
2) Если вам нужно динамически искать идентификатор, что делает невозможным создание фикстуры для каждого идентификатора, используйте предложение akmad с одним изменением. Сохраните список идентификаторов, значения которых не равны, и добавьте этот список в сообщение об ошибке. Будет чрезвычайно сложно диагностировать неудачный тест, в котором указывается только количество ошибок, поскольку вы не будете знать, какой идентификатор вызывает ошибки.
3) Я не знаю, насколько сложно это было бы сделать в NUnit, но в PyUnit, когда нам нужно запускать тесты на динамически сгенерированных данных, мы динамически создаем тестовые приспособления и прикрепляем их к классу TestCase, чтобы у нас не получилось тестируйте каждую часть данных, которая не проходит. Хотя я полагаю, что это было бы намного сложнее без динамических способностей Python.
Спасибо, я действительно искал ваш номер 3 ... но, как вы и сказали ... это .net :(
Исходя из поставленной вами цели, весь тест должен завершится ошибкой, если одна строка не соответствует другой. Подсчет количества успешных или неудачных попыток утверждения дает меньше информации, чем сравнение ожидаемого результата с результатом, который вы получили на самом деле.
Я знаю, что речь идет именно о NUnit, но, что интересно, Галлио / MbUnit имеет функцию, которая позволяет запускать и перехватывать сразу несколько утверждений.
[Test]
public void MultipleTest()
{
Assert.Multiple(() =>
{
Assert.IsTrue(blabla);
Assert.AreEqual(pik, pok);
// etc.
}
}
Assert.Multiple перехватывает все ошибочных утверждений и сообщает о них в конце теста.
У меня недавно была такая же проблема. Я объединил идею подсчета ошибок с упоминанием Янном Тревином 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
И решение проблемы OP было бы:
[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);
}
}
}
}
Вы можете использовать Атрибут [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()].
Я хочу заявить, что хранимая процедура работает для каждой строки в базе данных.