Nie znam żadnej sytuacji, w której dobrze byłoby mieć wiele twierdzeń w samej metodzie [Test]. Głównym powodem, dla którego ludzie lubią mieć wiele asercji, jest to, że próbują mieć jedną klasę [TestFixture] dla każdej testowanej klasy. Zamiast tego możesz podzielić swoje testy na więcej klas [TestFixture]. Pozwala to zobaczyć wiele sposobów, w których kod mógł nie zareagować w oczekiwany sposób, zamiast tylko tych, w których pierwsze potwierdzenie nie powiodło się. W ten sposób uzyskuje się testowanie co najmniej jednego katalogu na klasę z dużą ilością klas [TestFixture]. Każda klasa [TestFixture] zostałaby nazwana na podstawie określonego stanu testowanego obiektu. Metoda [SetUp] wprowadzi obiekt do stanu opisanego przez nazwę klasy. Następnie masz wiele metod [Testowych], z których każda potwierdza różne rzeczy, których oczekiwałbyś, że będą prawdziwe, biorąc pod uwagę obecny stan obiektu. Każda metoda [Test] jest nazwana na cześć tego, co twierdzi, z tym wyjątkiem, że może być nazwana na podstawie koncepcji zamiast po prostu odczytu kodu w języku angielskim. Następnie każda implementacja metody [Test] potrzebuje tylko jednego wiersza kodu, w którym coś potwierdza. Kolejną zaletą tego podejścia jest to, że testy są bardzo czytelne, ponieważ staje się całkiem jasne, co testujesz i czego oczekujesz, patrząc na nazwy klas i metod. Skaluje się to również lepiej, gdy zaczniesz zdawać sobie sprawę ze wszystkich małych przypadków krawędziowych, które chcesz przetestować, i gdy znajdziesz błędy. z wyjątkiem tego, że może być nazwany na podstawie koncepcji zamiast po prostu angielskiego odczytu kodu. Następnie każda implementacja metody [Test] potrzebuje tylko jednego wiersza kodu, w którym coś potwierdza. Kolejną zaletą tego podejścia jest to, że testy są bardzo czytelne, ponieważ staje się całkiem jasne, co testujesz i czego oczekujesz, patrząc na nazwy klas i metod. Skaluje się to również lepiej, gdy zaczniesz zdawać sobie sprawę ze wszystkich małych przypadków krawędziowych, które chcesz przetestować, i gdy znajdziesz błędy. z wyjątkiem tego, że może być nazwany na podstawie koncepcji zamiast po prostu angielskiego odczytu kodu. Następnie każda implementacja metody [Test] potrzebuje tylko jednego wiersza kodu, w którym coś potwierdza. Kolejną zaletą tego podejścia jest to, że testy są bardzo czytelne, ponieważ staje się całkiem jasne, co testujesz i czego oczekujesz, patrząc na nazwy klas i metod. Skaluje się to również lepiej, gdy zaczniesz zdawać sobie sprawę ze wszystkich małych przypadków krawędziowych, które chcesz przetestować, i gdy znajdziesz błędy. i czego oczekujesz, patrząc na nazwy klas i metod. Skaluje się to również lepiej, gdy zaczniesz zdawać sobie sprawę ze wszystkich małych przypadków krawędziowych, które chcesz przetestować, i gdy znajdziesz błędy. i czego oczekujesz, patrząc na nazwy klas i metod. Skaluje się to również lepiej, gdy zaczniesz zdawać sobie sprawę ze wszystkich małych przypadków krawędziowych, które chcesz przetestować, i gdy znajdziesz błędy.
Zwykle oznacza to, że ostatni wiersz kodu w metodzie [SetUp] powinien przechowywać wartość właściwości lub wartość zwracaną w zmiennej zmiennej prywatnej [TestFixture]. Następnie możesz twierdzić wiele różnych rzeczy na temat tej zmiennej instancji z różnych metod [Test]. Można również wysunąć twierdzenia na temat tego, jakie różne właściwości testowanego obiektu są ustawione na teraz, gdy jest on w pożądanym stanie.
Czasami po drodze musisz wprowadzić asercje, gdy testujesz obiekt w pożądanym stanie, aby upewnić się, że nie zepsułeś się przed wprowadzeniem obiektu w pożądany stan. W takim przypadku te dodatkowe twierdzenia powinny pojawić się w metodzie [SetUp]. Jeśli coś pójdzie nie tak w metodzie [SetUp], będzie jasne, że coś było nie tak z testem, zanim obiekt osiągnął pożądany stan, który zamierzałeś przetestować.
Innym problemem, na który możesz natknąć się, jest testowanie wyjątku, którego oczekiwano. Może to skusić Cię do nieprzestrzegania powyższego modelu. Jednak nadal można to osiągnąć, wychwytując wyjątek w metodzie [SetUp] i przechowując go w zmiennej instancji. Pozwoli ci to na stwierdzenie różnych rzeczy na temat wyjątku, każdy we własnej metodzie [Test]. Następnie możesz również potwierdzić inne rzeczy dotyczące testowanego obiektu, aby upewnić się, że nie wystąpiły niezamierzone skutki uboczne zgłoszonego wyjątku.
Przykład (byłoby to podzielone na wiele plików):
namespace Tests.AcctTests
{
[TestFixture]
public class no_events
{
private Acct _acct;
[SetUp]
public void SetUp() {
_acct = new Acct();
}
[Test]
public void balance_0() {
Assert.That(_acct.Balance, Is.EqualTo(0m));
}
}
[TestFixture]
public class try_withdraw_0
{
private Acct _acct;
private List<string> _problems;
[SetUp]
public void SetUp() {
_acct = new Acct();
Assert.That(_acct.Balance, Is.EqualTo(0));
_problems = _acct.Withdraw(0m);
}
[Test]
public void has_problem() {
Assert.That(_problems, Is.EquivalentTo(new string[] { "Withdraw amount must be greater than zero." }));
}
[Test]
public void balance_not_changed() {
Assert.That(_acct.Balance, Is.EqualTo(0m));
}
}
[TestFixture]
public class try_withdraw_negative
{
private Acct _acct;
private List<string> _problems;
[SetUp]
public void SetUp() {
_acct = new Acct();
Assert.That(_acct.Balance, Is.EqualTo(0));
_problems = _acct.Withdraw(-0.01m);
}
[Test]
public void has_problem() {
Assert.That(_problems, Is.EquivalentTo(new string[] { "Withdraw amount must be greater than zero." }));
}
[Test]
public void balance_not_changed() {
Assert.That(_acct.Balance, Is.EqualTo(0m));
}
}
}