как определяте, че 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
Казано по-ясно, дори комбинацията от тези 2 теста не доказва, че е възможно да напиша неуспешен тест с помощта на моето разширение NUnit. - person still_dreaming_1; 22.12.2010
comment
@INTPnerd: Редактирах отговора си, за да обясня мнението си малко по-добре. - person Jackson Pope; 22.12.2010
comment
Благодаря за обяснението. Съгласен съм с разсъжденията ви защо трябва да напиша теста, за да издържа, а не да се проваля. Въпреки това все още съм съгласен с разсъжденията си за това как комбинацията от тези 2 теста не доказва, че е възможно да се напише неуспешен тест. Изглежда, че в този случай нито писането на неуспешни тестове, нито преминаването на тестове би било идеално. Ако имаше начин да напиша неуспешни тестове, бих могъл да напиша издържаните тестове, които предложихте в допълнение към неуспешните тестове. Дори и тогава нямаше да съм доволен. Още идеи? - person still_dreaming_1; 23.12.2010
comment
Да, съгласен съм, че моите тестове не ви позволяват да пишете неуспешни тестове, които преминават. Каква е логиката, която се опитвате да тествате? Този TypeOf‹int› се проваля? Ако случаят е такъв, тогава напишете тест, който преминава, ако TypeOf‹int› е неуспешен, например ако TypeOf‹int› връща false, потвърдете, че резултатът е 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