Czy testy jednostkowe można traktować jako interfejs? Jak najbardziej!

2

Interfejs w programowaniu możemy rozumieć przynajmniej dwojako. Po pierwsze: interfejs użytkownika, czyli sposób na interakcję z aplikacją. Po drugie: interfejs jako kontrakt, implementowany przez klasy. Testy ładnie wpasowują się w… obie definicje!

Akcja: BLOGvember! Post nr 1.
W listopadzie w każdy roboczy poranek na devstyle.pl znajdziesz nowy, świeżutki tekst. W sam raz do porannej kawy na dobry początek dnia.
Miłej lektury i do przeczytania jutro! :)

Testy jako UI… a raczej DI

Interfejs użytkownika – User Interface – charakteryzuje się tym, że możemy po nim pochodzić, poeksperymentować, poklikać. Nakazać aplikacji COŚ zrobić.

A testy? Są doskonałym interfejsem programisty! Developer Interface. Mając aplikację porządnie pokrytą testami jesteśmy w stanie, nawet bez jej uruchamiania, zmusić ją do działania. Niezmiernie przydatna możliwość.

Nie czekamy na całą kompilację, nie czekamy na wdrożenie, rozgrzanie serwera. Uruchamiamy test i… i już. Oszczędzamy masę czasu.

Dawno temu natknąłem się na ciekawą anegdotkę. Podobno jedna z linii lotniczych w USA tak głęboko “weszła” w BDD (Behavior Driven Development), że nawet obsługa klienta poruszała się po systemie za pomocą… testów właśnie! Wyobraź sobie sytuację: podchodzisz do stanowiska, chcesz kupić bilet, a babka za ladą mówi: “Już już, puszczam test sprawdzający, czy mamy wolne miejsca na ten lot“. Szczena na ziemi, nie? Mam nadzieję, że to prawda.

Ba, mało tego: każdy test możemy uruchomić z podłączonym debuggerem! To bardzo często – a po kilku latach zdobywania doświadczenia: prawie zawsze – eliminuje konieczność podpinania się debuggerem do całego, wielkiego, działającego procesu. Nie musimy klikać na chybił-trafił w celu zreprodukowania błędu. Zamiast tego modelujemy scenariusz w postaci kodu testującego -> stawiamy breakpoint -> “run with debugger” -> done.

Przez lata całe nie debuggowałem całej aplikacji. Godziny, albo i nawet DNI, przez to zaoszczędziłem. Już w 2011r cytowałem Uncle Boba Martina:

Would you rather Test-First or Debug-Later?

No właśnie…

Uwaga, szkolonko!
Korzystając z okazji, zapraszam na moje jednodniowe szkolenie otwarte z pisania testów w .NET. Wszystkie szczegóły znajdziesz tutaj. Jeszcze tylko przez kilka dni można kupić bilet z rabatem 25%!

A co z drugą definicją interfejsu?

Testy jako interfejs – kontrakt

Dobrze napisane testy pełnią rolę dokumentacji naszego kodu. Dokumentacji, która – w przeciwieństwie do standardowej, tekstowej – zawsze będzie aktualna. Nigdy się nie rozsynchronizuje.

Pracowałem w wielu firmach. Niejednokrotnie pierwsze dni w nowym miejscu spędzałem czytając dziesiątki stron “dokumentacji technicznej” w Wordzie. Tylko po to, żeby na koniec usłyszeć: “wiesz co, w sumie to tego dokumentu i tak nikt od miesięcy nie aktualizował, więc pewnie w kodzie to wygląda trochę inaczej“. Z testami nie ma tego problemu. Muszą opisywać faktyczny, aktualny kod. W przeciwnym wypadku zaczną się wywalać.

Testy mówią programiście CO aplikacja robi. Niekiedy nie skupiają się nawet na tym JAK. Często szczegóły implementacyjne nie są widoczne z poziomu testów. I nie powinny być. W końcu mamy święty cykl TDD (więcej o możliwych podejściach do TDD poczytasz w tekście “Niezawodny sposób na naukę testów jednostkowych“):

clip_image001

Refactoring to proces modyfikacji struktury kodu bez zmiany jego działania. A więc: bez dotykania testów. Skoro tak, to testy są kontraktem. A kod: jego implementacją.

Sprytne, nie?

Share.

About Author

Programista, trener, prelegent, pasjonat, blogger. Autor podcasta programistycznego: DevTalk.pl. Jeden z liderów Białostockiej Grupy .NET i współorganizator konferencji Programistok. Od 2008 Microsoft MVP w kategorii .NET. Więcej informacji znajdziesz na stronie O autorze. Napisz do mnie ze strony Kontakt. Dodatkowo: Twitter, Facebook, YouTube.

2 Comments

  1. Pingback: dotnetomaniak.pl

  2. Z tym debugowaniem testów, to jest mój ulubiony patent. Właściwie w każdym projekcie mam jedną klasę testów nazwaną QuickTest i w niej jedną metodę AdHocTest, która służy mi do sprawdzania, jak coś działa, czyli zazwyczaj jak nie pamiętam niuansów (ostatnio np. nie byłem pewny jak się zdeserializuje XML przy powtarzających się tagach). Test ten zatem nie służy do testowania, ale do podglądania jak się zachowuje dana klasa/metoda .NET (na końcu jest Assert.AreNotEqual(“”, result), aby mi nie optymalizował resulta, na który zwracam wynik metody).