как вы указываете, что тест NUnit должен завершиться неудачей?

Есть ли способ указать, что вы хотите, чтобы тест NUnit завершился неудачно, а это означает, что о сбое следует сообщать как о прохождении, а о прохождении следует сообщать как о сбое? Это было бы полезно при тестировании ваших собственных расширений NUnit. Вот пример того, что я хотел бы сделать:

[Test]
[ExpectFail]
public void TypeOf_fail() {
    string str = "abc";
    str.Should().Be.TypeOf<int>();
}

Это не компилируется, потому что [ExpectFail] — это воображаемый атрибут, иллюстрирующий то, что я хочу сделать, но код внутри метода работает нормально. Эта проблема специфична для тестирования расширения NUnit, поскольку обычно вы можете просто написать свои тесты так, чтобы они проходили, а не терпели неудачу. В этом случае вам нужно доказать, что можно написать неудачный тест, используя расширение NUnit, которое вы тестируете.


person still_dreaming_1    schedule 21.12.2010    source источник
comment
Я никогда не вникал в это, но как основной код NUnit проверяет себя, чтобы доказать, что тест может провалиться?   -  person Michael Shimmins    schedule 22.12.2010


Ответы (4)


Как насчет Assert.Throws‹XXXException›(x.DoSomething());

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

Учитывая, что в этом случае вы хотите протестировать расширения NUnit, которые, как я предполагаю, функционируют, выполняя вызовы Assert, вы можете использовать Assert.Throws‹AssertionException›(...), а затем выполнить описанное выше.

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

person William Burgeson    schedule 31.07.2011

Модульные тесты должны быть разработаны таким образом, чтобы:
они устанавливали некоторое состояние
они запускали тестируемый метод
они утверждали, что одна вещь верна после завершения тестируемого метода

(ссылка: Искусство модульного тестирования Роя Ошерова)

Почему тесты, рассчитанные на провал, — это плохо? Они могут потерпеть неудачу неожиданным образом и все равно будут помечены как пройденные, потому что они не прошли. В вашем примере, предполагая, что Should() является тестируемым методом (хотя этот пункт остается, даже если это не так), вы пишете тест выше и помечаете его как «ожидаемый сбой». Это терпит неудачу. Все отлично. Через пару месяцев вы возвращаетесь к Should() и понимаете, что он нуждается в некотором рефакторинге, поэтому вы меняете его реализацию.

Теперь в вашем примере Should() выдает исключение, потому что вы случайно допустили ошибку. Но ваш тест (который сейчас не проходит из-за исключения, а не логики) помечен как не пройденный, и это так, поэтому он по-прежнему помечен как пройденный, несмотря на критическое изменение.

Тест должен быть разработан таким образом, чтобы он прошел, а не провалился, поэтому, если он не пройден каким-либо другим, неожиданным образом, вы будете уведомлены. Итак, в вашем примере вы должны написать тесты с противоположной логикой:

[Test]
public void TypeOf_ShouldBeString() {
    string str = "abc";
    str.Should().Be.TypeOf<string>();
}

or:

[Test]
public void TypeOf_ShouldNotBeInt() {
    string str = "abc";
    str.Should().Not.Be.TypeOf<int>();
}

(Не уверен в синтаксисе, который вы используете, поэтому, вероятно, не нужно будет заменять правильный синтаксис, но настроение сохраняется).

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

[Test]
[ExpectedException(typeof(AssertionException))]
public void ShouldBeTypeOf_WithInt_Fails() {
    string str = "abc";
    str.Should().Be.TypeOf<int>();
}    
person Jackson Pope    schedule 21.12.2010
comment
Мне не нравится это решение, потому что ни один из тех тестов, которые вы опубликовали, не доказывает, что можно использовать расширение таким образом, что это приведет к неудачному тесту. - person still_dreaming_1; 22.12.2010
comment
Проще говоря, даже комбинация этих двух тестов не доказывает, что можно написать тест с ошибкой, используя мое расширение NUnit. - person still_dreaming_1; 22.12.2010
comment
@INTPnerd: я отредактировал свой ответ, чтобы немного лучше объяснить свою точку зрения. - person Jackson Pope; 22.12.2010
comment
Спасибо за объяснение. Я согласен с вашими рассуждениями о том, почему я должен писать тест, чтобы он прошел, а не провалился. Тем не менее, я также по-прежнему согласен с моими рассуждениями о том, что комбинация этих двух тестов не доказывает, что можно написать провальный тест. Кажется, что в этом случае ни написание проваленных тестов, ни прохождение тестов не будут идеальными. Если бы был способ написать тесты с ошибками, я мог бы написать предложенные вами тесты на прохождение в дополнение к тестам с ошибками. Но даже тогда я не был бы удовлетворен. Есть еще идеи? - person still_dreaming_1; 23.12.2010
comment
Да, я согласен, что мои тесты не позволяют вам писать неудачные тесты, которые проходят. Какую логику вы пытаетесь проверить? Что TypeOf‹int› терпит неудачу? Если это так, напишите тест, который проходит, если TypeOf‹int› терпит неудачу, например, если TypeOf‹int› возвращает false, утверждает, что результат является ложным, или если он генерирует исключение, используйте [ExpectedException]. - person Jackson Pope; 23.12.2010
comment
Я не знал, что утверждения NUnit вызывают исключения, когда они терпят неудачу, спасибо! - person still_dreaming_1; 28.12.2010

Я знаю, что это старый пост, но вот что мне помогло, используя NUnit:

[TestCase("SomeValidValue")]
[TestCase("{3X5XFX9X-7XCX-4XCX-8X3X-3XAXEX9X0XBX}", ExpectedException = typeof(AssertionException))]
public void GetSpecificConfiguration(string key)
{
    Assert.IsNotNull(Config.Instance.GetRecord(key));
}

Этот подход позволяет мне провести один и тот же тест с двумя ожиданиями, одним успешным и одним неудачным.

person Darek    schedule 06.10.2014

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

[Test]
[ExpectedException(typeof(Exception))]
public void TypeOf_fail() {
    string str = "abc";
    str.Should().Be.TypeOf<int>();
}

Конечно, замените Exception наиболее конкретным возможным исключением.

person Robert Bratton    schedule 22.08.2014