Testy jednostkowe - dobre praktyki

Spotkałem się z problemem nazewnictwa testów jednostkowych, jak pisać oraz co w nich sprawdzać. Sposobów rozwiązania tych wszystkich problemów jest masę. Przedstawię kilka dobrych zasad, które pozwolą na długą i owocną pracę z testami. Spróbuje je wytłumaczyć i pokazać zalety takiego prowadzenia testów.

Nazewnictwo

Najważniejszą zasadą jest to, aby nazwy testów przedstawiały nam jasno co one testują. Nie ważne jak to uzyskacie. Ważne, aby powracając nawet po kilku latach nie mieć problemów z odczytaniem co test miał testować.

Dlaczego to takie ważne? Mam kilka argumentów do tej zasady:

  • Testów jest dużo więcej niż logiki, dlatego jest duża szansa, że nie będziemy pamiętać co dany test robił.
  • Z jasnymi nazwami testów, gdy przestanie nam działać duża ilość, możemy bez zaglądania w kod wywnioskować co się po zepsuło.
  • Metod testów nie używa się w logice, w kodzie, nigdzie. Z tego powodu ani konwencja nazewnicza, ani długa nazwa, ani cyfry, znaczki, cokolwiek nie będzie przeszkadzało w ich używaniu. Nazwa służy tylko do poinformowania co dany test robi i tyle.

Ilość linii testu

Uważam, że testy powinny być krótkie, a nawet jeżeli są krótkie to zawsze mogą być jeszcze krótsze. Powiecie mi pewnie teraz, że nie zawsze się da. Owszem da się zawsze, trzeba tutaj tylko odpowiedzieć sobie na pytanie czy funkcja, którą testujemy, nie jest napisania źle. Uzyskując krótką metodę, która działa na jednym poziomie abstrakcji i jednocześnie wykonuje jedne działanie, na pewno będziemy w stanie napisać krótki test.

Dlaczego test powinien być krótki?

Pewnie każdy programista spotkał się z długimi funkcjami oraz testami. Teraz przypomnijmy sobie czy szczegółowo czytaliśmy co się w nim dzieje i czy to było łatwe. Przypuszczam, że nie i analiza takiego kodu była udręką. Test powinien być łatwy do analizy, powinniśmy w łatwy sposób sprawdzić jakie dane trzeba użyć dla funkcji testowanej, aby uzyskać oczekiwany wynik. Jeżeli dane będą produkowane przez 20 linii, a wynik sprawdzany przez 10, przypuszczam, że duża część osób czytająca ten test przestanie go czytać. Dlaczego? Ponieważ, nikt nie będzie wiedział jaki jest oczekiwany wynik i jakie konkretne dane są używane do jego uzyskania.

Wygląd testu

Myślę, że jedną z najbardziej przyjemną metodyką do pisania testów jest given, when, then. Na czym to polega? Polega na tym, aby test układał się na trzy następujące po sobie sekcje:

  • Sekcja given, czyli przygotowanie danych do testów.
  • Sekcja when, czyli wywołanie funkcji.
  • Sekcja then, czyli weryfikacja wyniku funkcji.

Nazw metodyk oraz tłumaczeń Ich jest duża ilość, lecz wszystkie dążą do jednego. Aby kod układał się w pewien przebieg wydarzeń, który łatwo przeczytać.

Testy powinny być autonomiczne

To bardzo ułatwia edycję logiki i testów. Nie staramy się wyodrębniać funkcji dla grupy testów. A co najgorsze dla testów różnych funkcjonalności. Zapytacie dlaczego? To marnotrawstwo naszego cennego czasu. W późniejszym etapie projektu logika w cale nie musi w tych dwóch miejscach być taka sama (jeżeli jest powinna powstać jedna tylko funkcja do testowania a nie dwie podobne). Gdy nagle logika w jednym miejscu zmieni się to nie powinniśmy poprawiając testów do tej logiki popsuć ich dla drugiej funkcjonalności.

Prostota

Testy powinny być proste. Nie zawierać zawiłej logiki. Każdy fragment takiego testu może być problematyczny i powodować błędy w działaniu. Posiadając błędny test (który wydaje nam się na dobry), nie powoduje, że jesteśmy pewni swojego kodu w logice. Ba, jest jeszcze większa szansa, że kod jest błędny, skoro błędny test przechodzi poprawnie.

Podsumowanie

Wszystkie zasady dążą do jednego. Próbujemy uzyskać testy proste dla programisty, który będzie je czytał. Każdy pewnie myśli, po co myśleć o kimś innym w trakcie pisania testu. Testy są potrzebne tu i teraz. I tutaj jest właśnie błąd myślenia. Testy też są na przyszłość, aby sprawdzić co się zepsuło w trakcie modyfikacji kodu, aby w prosty sposób wywnioskować źródło błędu oraz po prostu sprawdzić czy nic nie zepsuliśmy dopisując nasz kod. Jednocześnie szukając jak wykorzystać poprawnie funkcję możemy rozwiązania szukać w testach. Także, gdy funkcja którą używamy zwraca jakiś błąd możemy zweryfikować dlaczego on jest zwracany i pod jakimi warunkami. Dobrze napisane testy są lepsze niż dokumentacja i o tym przekonacie się stosując te proste zasady. Pamiętać trzeba, że ciekawych dobrych praktyk pisania testów jednostkowych jest wiele więcej niż tutaj przedstawiłem. Jednakże wiele z nich wychodzą z zasad przedstawionych w przeczytanym przez Was wpisie. Zachęcam do zostawienia komentarza i wdania się w dyskusje na ten temat.

Comments

Popular posts from this blog

Why TDD is bad practice?

How correctly imitate dependencies?

Software development using Angular 5 with Spring Boot