Spis treści
Co zrobić, aby kod był testowalny i co to w ogóle znaczy?
Testowalny kod to taki, do którego można bez problemu przygotować zestaw dokładnych testów jednostkowych. Metody muszą spełniać trzy podstawowe zasady, aby były testowalne:
- muszą być zwięzłe, tzn. krótkie – im krótsze, tym lepsze (kilka – kilkanaście linii kodu),
- muszą robić jedną rzecz,
- nie mogą zależeć od użytkownika.
Dlaczego testowalny kod musi spełniać takie wymogi? Im mniej akcji wykonuje metoda, tym mniej testów jednostkowych będzie wymagała, i tym prostsze one będą. Jeżeli napiszemy metodę na 100 linii kodu, która będzie robiła kilkanaście rzeczy, trudno będzie napisać testy jednostkowe, które sprawdzą wszystkie możliwe ścieżki wykonania i przetestują wszystkie funkcjonalności.
Dodatkowo, metody, które wymagają od programisty wykonania jakiejś akcji, są niewygodne, ponieważ nie chcemy być zmuszeni do interakcji z naszymi testami, które będziemy często uruchamiać i których mogą być tysiące.
Powinniśmy dążyć do rozbicia dużych metod na małe, wydzielone jednostki, które otestujemy, a następnie, będąc upewnieni, że działają, będziemy z nich korzystać w kolejnych metodach.
Spójrzmy na poniższą metodę i zastanówmy się nad następującymi pytaniami:
- Czy taką metodę łatwo przetestować?
- Ile operacji wykonuje ta metoda?
- Czy możemy ją usprawnić, aby można ją było przetestować w łatwy sposób?
import java.util.Scanner; public class TestowanieCzyParzysta { public static void main(String[] args) { czyParzysta(); } public static void czyParzysta() { System.out.println( "Prosze podac liczbe - sprawdze, czy jest parzysta." ); int liczba = getInt(); if (liczba % 2 == 0) { System.out.println("Ta liczba jest parzysta."); } else { System.out.println("Ta liczba jest nieparzysta"); } } public static int getInt() { return new Scanner(System.in).nextInt(); } }
- Bez interakcji użytkownika metoda ta jest nie do przetestowania. Pyta ona użytkownika o liczbę i czeka na jej podanie. W obecnej formie, aby ją przetestować, musielibyśmy uruchomić powyższy program wielokrotnie, wpisując w oknie konsoli różne liczby i sprawdzić wynik wypisany na ekranie.
- Metoda ta wykonuje wiele operacji:
- Wypisuje komunikat z prośbą o podanie liczby.
- Pobiera od użytkownika liczbę przy użyciu metody getInt.
- Sprawdza parzystość liczby.
- Na podstawie parzystości liczby wypisuje komunikat.
- Zastanówmy się, co moglibyśmy usprawnić w naszej metodzie?
- Najważniejsze to przenieść pobieranie liczby od użytkownika poza metodę czyParzysta. Dzięki temu nasza metoda nie będzie już uzależniona od użytkownika.
- Skoro nie będziemy pobierać liczby w metodzie czyParzysta, to musimy jakoś przesłać do tej metody liczbę do sprawdzenia – łatwo możemy to osiągnąć, gdy zmienimy metodę, by przyjmowała jeden argument typu int.
- Nasza metoda nie powinna wypisywać na ekran wyniku sprawdzenia parzystości – ktokolwiek będzie używał naszej metody powinien sam zadecydować, co chce z tą informacją (czy liczba jest parzysta czy nie) zrobić. Skoro tak, to nasza metoda powinna zwrócić informację o tym, czy liczba jest parzysta czy nie – osiągniemy to poprzez zmianę zwracanego przez metodę typu z void na boolean (prawda / fałsz).
Spójrzmy na usprawnioną wersję powyższego program:
import java.util.Scanner; public class TestowanieCzyParzystaWersja2 { public static void main(String[] args) { // (1) System.out.println( "Prosze podac liczbe - sprawdze, czy jest parzysta." ); int liczba = getInt(); // (2) if (czyParzysta(liczba)) { System.out.println("Ta liczba jest parzysta."); // (3) } else { System.out.println("Ta liczba jest nieparzysta"); // (4) } } // (5) (6) public static boolean czyParzysta(int x) { return x % 2 == 0; // (7) } public static int getInt() { return new Scanner(System.in).nextInt(); } }
Wykonane zmiany:
- Przeniesienie wypisania prośby o podanie liczby (1).
- Przeniesienie pobierania liczby od użytkownika (2).
- Przeniesienie wypisywania komunikatu zależnego od parzystości liczby (3) (4).
- Zmiana typu zwracanego przez metodę czyParzysta z void na boolean (5).
- Dodanie argumentu do metody czyParzysta, który ma być sprawdzony pod kątem parzystości (6).
- Zwrócenie informacji, czy przesłana w argumencie liczba jest parzysta, czy nie (7).
Dzięki powyższym zmianom, metoda czyParzysta bardzo się uprościła. Wykonuje ona teraz jedno konkretne zadanie, którym jest sprawdzenie parzystości podanego do niej argumentu i zwrócenie wyniku. Taką metodę łatwo przetestować – wystarczy napisać testy, które wywołają metodę czyParzysta z różnymi wartościami i sprawdzą wynik. Takie testy będą: szybkie, proste, i nie będą wymagały w trakcie wykonywania żadnych akcji od programisty.