Spis treści
- Testy mają na celu sprawdzenie, czy nasz kod działa zgodnie z założeniami.
- Testy jednostkowe testują najmniejsze jednostki naszych programów – metody.
- Testy jednostkowe to także metody – są to metody, które uruchamiają metodę, którą testują, z różnymi parametrami i sprawdzają, czy wynik działania testowanej metody jest taki, jak zakładaliśmy.
- Musimy tworzyć nasze metody w taki sposób, by były one testowalne. Oznacza to, że nasze metody:
- powinny być krótkie (kilka do kilkunastu linii kodu) – im mniej metoda robi, tym łatwiej ją przetestować, ponieważ potrzeba mniejszej liczby przypadków testowych,
- powinny robić jedną, ustaloną rzecz – wtedy przypadki testowe będą łatwiejsze do przygotowania,
- nie powinny oczekiwać na żadne akcje użytkownika – ponieważ wtedy wykonanie testów będzie za każdym razem oczekiwało działań od użytkownika.
- Testy jednostkowe są ważne, ponieważ:
- pozwalają nam na wyizolowanie i przetestowanie najmniejszych części naszego programu,
- wymuszają styl tworzenia kodu, który jest czytelniejszy i łatwiejszy w utrzymaniu (ponieważ metody są krótsze, a co za tym idzie, łatwiej zrozumieć, co się w nich dzieje),
- pomagają nam dostarczać działający kod,
- posiadanie zestawu testów pozwala na wprowadzanie zmian do kodu bez obawy, że coś zepsujemy – po wprowadzeniu zmiany możemy uruchomić testy i upewnić się, że przechodzą one bez błędów
- Testy testują kod produkcyjny – kod produkcyjny testuje testy.
- O testy należy dbać niemniej, niż o kod produkcyjny.
- Dobre testy jednostkowe:
- sprawdzają wszystkie możliwe ścieżki wykonania metody,
- są krótkie,
- są czytelne i schludnie napisane,
- są szybkie.
- Różne przypadki testowe powinny być obsługiwane w osobnych metodach testujących.
- Testy powinny informować jedynie o błędnych przypadkach, tzn. takich, gdzie zakładana wartość była inna, niż faktyczny rezultat wykonania testowanej metody.
- Powinniśmy przygotowywać wiele przypadków testowych, by mieć pewność, że nasza metoda będzie działała zgodnie z oczekiwaniami niezależnie od danych wejściowych.
- Nie powinniśmy duplikować przypadków testowych – każdy test powinien testować pewien określony przypadek. Dla przykładu – nie ma sensu testować, czy metoda podnosząca liczbę do kwadratu zwróci poprawną wartość dla liczb 1, 2, 3 itd. – wystarczy test dla liczby np. 5.
- Istnieje wiele konwencji nazewniczych testów – jedna z nich zakłada, że najpierw podajemy nazwę testowanej metody, następnie dane wejściowe, a na końcu opisujemy spodziewany wynik:
- nazwaTestowanejMetody_daneWejściowe_spodziewanyWynik
- na przykład:
- doKwadratu_wartoscDodatnia_wartoscPodniesionaDoKwadratu
- Typem zwracanym metod testowych powinien być void.
- Podczas pisania testów często używa się tzw. asercji. Są to metody, które sprawdzają pewien warunek, na przykład czy dwie liczby są sobie równe. Jeżeli nie, informują o błędzie, a w przeciwnym razie, gdy warunek jest spełniony, nie wykonują żadnych akcji. Przykład:
public static void assertEquals(int expected, int actual) { if (expected != actual) { System.out.println("Spodziewano sie liczby " + actual + ", ale otrzymano: " + expected); } }
- Given .. when .. then to konwencja definiująca, jak testy jednostkowe powinny być ustrukturyzowane. Najpierw przygotowujemy dane wejściowe dla testu (given), następnie wywołujemy testowaną metodę z użyciem przygotowanych danych (when), a na końcu sprawdzamy wynik (then):
- dla takich a takich danych (given),
- gdy wykonam taką metodę (when),
- powinienem otrzymać taki a taki rezultat (then).
Przykład testu o strukturze given .. when .. then:
public static void czyZawieraElement_brakSzukanegoElementu_zwrociFalse() { // given int[] tablica = {-20, 100, 500}; int liczba = 128; // when boolean czyZawiera = czyZawieraElement(tablica, liczba); // then if (czyZawiera) { System.out.println("Blad! Element 128 nie powinien byc znaleziony."); } }
- TDD, czyli Test Driven Development, to metodologia tworzenia oprogramowania, w której najpierw zaczynamy tworzenie kodu od napisania testu, a dopiero potem piszemy kod, które ten test ma spełnić. Działamy w ten sposób aż do momentu, aż nie uznamy kodu produkcyjnego za gotowy.