Rozdział 8 - Testowanie kodu - Testowalny kod

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.

Małe metody to maksymalnie kilka-kilkanaście linijek kodu.

Spójrzmy na poniższą metodę i zastanówmy się nad następującymi pytaniami:

  1. Czy taką metodę łatwo przetestować?
  2. Ile operacji wykonuje ta metoda?
  3. Czy możemy ją usprawnić, aby można ją było przetestować w łatwy sposób?
Nazwa pliku: TestowanieCzyParzystaWersja1.java
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();
  }
}
  1. 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.
  2. Metoda ta wykonuje wiele operacji:
    1. Wypisuje komunikat z prośbą o podanie liczby.
    2. Pobiera od użytkownika liczbę przy użyciu metody getInt.
    3. Sprawdza parzystość liczby.
    4. Na podstawie parzystości liczby wypisuje komunikat.
  3. Zastanówmy się, co moglibyśmy usprawnić w naszej metodzie?
    1. 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.
    2. 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.
    3. 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:

Nazwa pliku: TestowanieCzyParzystaWersja2.java
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:

  1. Przeniesienie wypisania prośby o podanie liczby (1).
  2. Przeniesienie pobierania liczby od użytkownika (2).
  3. Przeniesienie wypisywania komunikatu zależnego od parzystości liczby (3) (4).
  4. Zmiana typu zwracanego przez metodę czyParzysta z void na boolean (5).
  5. Dodanie argumentu do metody czyParzysta, który ma być sprawdzony pod kątem parzystości (6).
  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.

Dodaj komentarz

Twój adres email nie zostanie opublikowany.