Как игнорировать тест на основе другого теста в NUnit?

Я пишу несколько тестов NUnit для операций с базой данных. Очевидно, что если Add() терпит неудачу, то Get() тоже не удастся. Тем не менее, он выглядит обманчивым, когда оба Add() и Get() терпят неудачу, потому что это выглядит как две проблемы, а не только одна.

Есть ли способ указать "порядок" для запуска тестов, в том случае, если при первом тестировании не выполняются следующие тесты:

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

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

Изменить: Кажется, что некоторым людям не хватает смысла. Я не делаю этого:

[Test]
public void AddTest()
{
    db.Add(someData);
}

[Test]
public void GetTest()
{
    db.Get(someData);
    Assert.That(data was retrieved successfully);
}

Скорее, я делаю это:

[Test]
public void AddTest()
{
    db.Add(someData);
}

[Test]
public void GetTest()
{
    // need some way here to ensure that db.Add() can actually be performed successfully
    db.Add(someData);
    db.Get(somedata);
    Assert.That(data was retrieved successfully);
}

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

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

Ответ 1

NUnit поддерживает синтаксис "Assume.That" для проверки установки. Это документируется как часть Theory (спасибо clairestreb). В пространстве имен NUnit.Framework находится класс Assume. Чтобы процитировать документацию:

/// Provides static methods to express the assumptions
/// that must be met for a test to give a meaningful
/// result. If an assumption is not met, the test
/// should produce an inconclusive result.

Итак, в контексте:

public void TestGet() {
    MyList sut = new MyList()
    Object expecting = new Object();
    sut.Put(expecting);
    Assume.That(sut.size(), Is(1));
    Assert.That(sut.Get(), Is(expecting));
}

Ответ 2

Тесты никогда не зависят друг от друга. Вы только выяснили, почему. Тесты, которые зависят друг от друга, по определению являются хрупкими. Если вам нужны данные в БД для теста для Get(), поместите его там на шаге настройки.

Ответ 3

Я думаю, проблема заключается в том, что вы используете NUnit для запуска чего-то другого, кроме того, что было проведено NUnit, которое выполнялось NUnit.

По сути, вы хотите, чтобы AddTest запускался до GetTest, и вы хотите, чтобы NUnit прекратил выполнение тестов, если AddTest завершился с ошибкой.

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

Стандартная концепция Unit Testing заключается в том, что если у вас есть тест по функциональности "Добавить", вы можете использовать функциональность "Добавить" в тесте "Get", а не беспокоиться о том, работает ли "Добавить" в поле "Добавить", Получить 'тест. Вы знаете, что "Add" работает - у вас есть тест для этого.

Принцип "ПЕРВЫЙ" (http://agileinaflash.blogspot.com/2009/02/first.html) описывает, как должны вести себя тесты Unit. Тест, который вы хотите написать, нарушает как "I" (Изолированный), так и "R" (Повторяется).

Если вы беспокоитесь о том, что соединение с базой данных происходит между двумя вашими тестами, я бы рекомендовал вместо того, чтобы подключаться к реальной базе данных во время теста, ваш код должен использовать какой-то интерфейс данных, а для теста вы должен использовать макет интерфейса. Если точкой теста является использование соединения с базой данных, вы можете просто использовать неправильный инструмент для задания - это не действительно Unit test.

Ответ 4

Я не думаю, что это возможно из коробки.

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

Ответ 5

MbUnit, похоже, имеет DependsOnAttribute, который позволит вам делать то, что вы хотите.

Если другое тестовое приспособление или тест метод терпит неудачу, то этот тест не будет запустить. Кроме того, силы зависимости этот тест для запуска после этого зависит от.

Не знаю ничего о NUnit.

Ответ 6

Вы не можете принять какой-либо порядок выполнения тестового устройства, поэтому любые предварительные условия должны быть проверены в пределах ваших тестовых классов.

Разделите свой тест Add на один тестовый класс, например. AddTests, и поместите тест Get в другой тестовый класс, например. класс GetTests.

В методе [TestFixtureSetUp] класса GetTests убедитесь, что у вас есть рабочий доступ к базе данных (например, Add work), а если нет, Assert.Ignore или Inconclusive, как вы сочтете нужным.

Это приведет к прерванию тестового оборудования GetTests, когда его предварительные требования не будут выполнены, и пропустите попытку запустить любой из тестируемых модулей. (Я думаю, что я новичок nUnit.)

Ответ 7

Создайте глобальную переменную и вернитесь в тесте для Get, если Add не установите для нее значение true (сделайте это в последней строке Add):

public boolean addFailed = false;
public void testAdd () {
    try {
        ... old test code ...
    } catch (Throwable t) { // Catch all errors
        addFailed = true;
        throw t; // Don't forget to rethrow
    }
}
public void testGet () {
    if (addFailed) return;
    ... old test code ...
}