fbpx
devstyle.pl - Blog dla każdego programisty
devstyle.pl - Blog dla każdego programisty
2 minut

VatCalculator – przykład testów jednostkowych w nUnit 2.5


12.11.2009

Niedawno opublikowałem posta o tym, jak nie należy pisać testów jednostkowych. Przytoczony przykład powodował bezsensowną duplikację kodu w aplikacji i testach.

Dzisiaj bardzo krótka demonstracja tego, jak można zastosować atrybut ValuesAttribute z NUnit 2.5 do wygenerowania testów dla więcej niż jednej wartości naraz. Testować będziemy klasę, która oblicza 22%-ową stawkę podatku VAT. Jej implementacja jest oczywiście banalna:

  1:  public class VatCalculator
  2:  {
  3:  	public double Calculate(double netto)
  4:  	{
  5:  		if (netto < 0)
  6:  			throw new ArgumentException();
  7:  
  8:  		return netto * 0.22;
  9:  	}
 10:  }

Testów też nie można nazwać skomplikowanymi:

Zobaczcie jak za pomocą jednej deklaracji testu można uzyskać dość szczegółowe obłożenie testowanej metody różnymi wartościami! Co więcej, atrybut ValueSourceAttribute pozwala na dynamiczne dostarczanie takich wartości do testu.

Kolejnym aspektem, na który warto zwrócić uwagę, jest SequentialAttribute. Gdybym go w tym miejscu nie zastosował, zamiast niego nUnit wykorzystałby CombinatorialAttribute i wygenerował testy dla każdej możliwej pary wartości: [3562.5, 783.75], [3562.5, 0] i [0, 783.75]. A w tym przypadku jest to oczywiście niepożądane.

Uwaga kolejna dotycząca obsługi wyjątków. Jak można zauważyć, wolę konstrukcję Assert.Throws niż atrybut ExpectedException. Powody są dwa: 1) moim zdaniem lepiej wyraża ona intencje twórcy testu; 2) wspomniany atrybut jest niepoprawnie interpretowany przez niektóre narzędzia uruchamiające testy (w tym niestety test-runner z Resharpera).

I uwaga ostatnia: wszystko pięknie i ładnie, ale niestety “uruchamiacz” Resharperowy, którego używam na co dzień, nie potrafi poprawnie rozpoznać testu z omawianymi konstrukcjami… i je po prostu ignoruje. Na szczęście w wersji 5.0 się to zmieni (R# JIRA).

0 0 votes
Article Rating
5 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
PiotrB
14 years ago

Trzy rzeczy:
– klasa i jej testy nie uwzględnia różnic w zaokrągleniach między przepisami w .pl a .NET,
– w zasadzie ujemne wartości na wejściu powinny być dopuszczalne, np. przy korektach (to IMHO),
– warto może byłoby może pokazać w kolejnym odcinku rozbudowę klasy i jej testów np. o liczenie VAT od brutto (to o tyle ciekawy przypadek, że występuje również w realnym świecie i wymaga pewnych zmian w istniejącym kodzie (kilka prostych decyzji trzeba podjąć przy rozbudowie).

procent
14 years ago

@PiotrB:
Założeniem posta było przedstawienie pewnego podejścia do pisania testów jednostkowych, a jako przykład wybrałem mnożenie pewnej liczby x0.22 – i tyle. Sposób naliczania podatku i tym podobne bzdury mnie tak naprawdę nie interesują, od tego mam program do wystawiania faktur i księgową:).

PiotrB
14 years ago

@procent:
Oczywiście, domyśliłem się. Natomiast uważam, że warto byłoby pokazać rozbudowę jakiejś klasy (niekoniecznie powyższej, choć dodanie obliczania z brutto jest klasycznym przykładem "feature requesta") z wykorzystaniem TDD. Często spotykam się z opinią, że TDD to tylko do sprawdzenia czy 2+2=4 i tak sobie teraz myślę, że to też wynika ze stosowanych (przez ewangelistów TDD) przykładów. Oczywiście rozumiem, że to tylko prezentacja jednej ciekawej funkcji nunita, ale myślę, że taka bardziej rozbudowana prezentacja _WARTOŚCI_ TDD w Twoim stylu byłaby bardzo interesująca.

Gutek
14 years ago

Zgadzam sie z tym iz przyklady TDD w netcie sa slabe, ale zas jezeli (@PiotrB) otworzysz projekty Open Source to mozesz spotkac tam bardz fajne i trudne przypadki w jakich TDD jest wykorzystywane.

Jednak wciaz to nie zmienia faktu malo pisania o tym w netcie :)

Gutek

Kurs Gita

Zaawansowany frontend

Szkolenie z Testów

Szkolenie z baz danych

Książka

Zobacz również