Rozdział 8 - Testowanie kodu - Przykłady testów jednostkowych

Poniżej przedstawionych zostało kilka przykładów testów jednostkowych różnych metod.

Wartość bezwzględna

Spójrzmy na prosty przykład testów metody, której zadaniem jest zwrócenie wartości bezwględnej przesłanej liczby.

Wartość bezwzględna to wartość liczby bez uwzględnienia jej znaku.
Dla liczb parzystych jest to ta sama liczba. Przykład: wartość bezwzględna liczby 10 to 10.
Dla liczb ujemnych jest to liczba bez minusa. Przykład: wartość bezwzględna liczby -5 to 5.

Zanim jednak przejdziemy do kodu źródłowego, zastanówmy się jak przetestowalibyśmy taką metodę? Jakie przypadki testowe wzięlibyśmy pod uwagę?

Nazwa pliku: TestowanieWartoscBezwzgledna.java
public class TestowanieWartoscBezwzgledna {
  public static void main(String[] args) {
    wartoscBezwgledna_liczbaDodatnia_zwrociDodatniaWartosc(); // (1)
    wartoscBezwgledna_liczbaUjemna_zwrociDodatniaWartosc();   // (2)
  }

  public static int wartoscBezwgledna(int x) { // (3)
    return x < 0 ? -x : x;
  }

  public static void
      wartoscBezwgledna_liczbaDodatnia_zwrociDodatniaWartosc() { // (4)

    int rezultat = wartoscBezwgledna(20); // (5)

    if (rezultat != 20) { // (6)
      System.out.println( // (7)
        "Dla wartosci 20 otrzymano nieprawidlowa wartosc: " + rezultat
      );
    }
  }

  public static void
      wartoscBezwgledna_liczbaUjemna_zwrociDodatniaWartosc() { // (8)

    int rezultat = wartoscBezwgledna(-1); // (9)

    if (rezultat != 1) { // (10)
      System.out.println( // (11)
        "Dla wartosci -1 otrzymano nieprawidlowa wartosc: " + rezultat
      );
    }
  }
}

Przejdźmy krok po kroku przez powyższy kod:

  • Metoda, którą chcemy przetestować, to wartoscBezwzgledna (3). Jest to prosta metoda wykonując jedno zadanie – dla podanej jako argument liczby zwraca wartość bezwzględną tej liczby.
  • Metoda wartoscBezwzgledna testowana jest przez dwie metody (4) (8).
  • Dane testowe pierwszej metody to liczba dodatnia (5), a drugiej metody – liczba ujemna (9).
  • Obie metody testowe sprawdzają, czy wynik jest nieprawidłowy (6) (10) – jeśli tak, to wypisują informację na ekran (7) (11).
  • Metody testowe wywołujemy w metodzie main (1) (2).

Metoda sprawdzająca, czy tablica zawiera element

Chcielibyśmy napisać metodę, która będzie przyjmowała jako argument tablicę liczb i odpowiadała na pytanie, czy w tej tablicy znajduje się dana liczba.

Jakie przypadki testowe powinniśmy przygotować?

Powinniśmy na pewno sprawdzić następujące przypadki:

  1. Co się stanie, jeżeli tablica jest pusta? – zawsze warto sprawdzić zachowanie na "pustych" danych.
  2. Co się stanie, jeżeli niepusta tablica nie zawiera szukanego elementu? – podczas wyszukiwania elementów warto sprawdzić co dzieje się, gdy element nie istnieje.
  3. Co się stanie, jeżeli niepusta tablica zawiera szukany element? – "normalny" przypadek.
  4. Co się stanie, jeżeli niepusta tablica zawiera szukany element wyłącznie na samym początku tablicy? – w przypadku operacji na tablicach warto brać pod uwagę przypadki testowe sprawdzające zachowanie biorące pod uwagę pierwszy element tablicy.
  5. Co się stanie, jeżeli niepusta tablica zawiera szukany element wyłącznie na samym końcu tablicy? – jak wyżej, ale tym razem bierzemy pod uwagę element końcowy.

Poniższy kod źródłowy przedstawia, jak moglibyśmy napisać powyższy program wraz z testami:

Nazwa pliku: TestowanieCzyElementWTablicy.java
public class TestowanieCzyElementWTablicy {
  public static void main(String[] args) {
    czyZawieraElement_pustaTablica_zwrociFalse();
    czyZawieraElement_brakSzukanegoElementu_zwrociFalse();
    czyZawieraElement_zawieraSukanyElement_zwrociTrue();
    czyZawieraElement_zawieraSukanyElementNaPoczatku_zwrociTrue();
    czyZawieraElement_zawieraSukanyElementNaKoncu_zwrociTrue();
  }

  public static boolean czyZawieraElement(int[] tablica, int liczba) {
    for (int i = 0; i < tablica.length; i++) {
      if (tablica[i] == liczba) {
        return true;
      }
    }

    return false;
  }

  public static void czyZawieraElement_pustaTablica_zwrociFalse() {
    // given
    int[] pustaTablica = {};
    int liczba = 5;

    // when
    boolean czyZawiera = czyZawieraElement(pustaTablica, liczba);

    // then
    if (czyZawiera) {
      System.out.println(
          "Blad! Pusta tablica nie powinna nic zawierac."
      );
    }
  }

  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."
      );
    }
  }

  public static void czyZawieraElement_zawieraSukanyElement_zwrociTrue() {
    // given
    int[] tablica = {2, 4, 8, 16, 32, 64, 128, 256};
    int liczba = 128;

    // when
    boolean czyZawiera = czyZawieraElement(tablica, liczba);

    // then
    if (!czyZawiera) {
      System.out.println(
          "Blad! Element 128 powinien byc znaleziony."
      );
    }
  }

  public static void czyZawieraElement_zawieraSukanyElementNaPoczatku_zwrociTrue() {
    // given
    int[] tablica = {100, 200, 300};
    int liczba = 100;

    // when
    boolean czyZawiera = czyZawieraElement(tablica, liczba);

    // then
    if (!czyZawiera) {
      System.out.println(
          "Blad! Element 100 powinien byc znaleziony."
      );
    }
  }

  public static void czyZawieraElement_zawieraSukanyElementNaKoncu_zwrociTrue() {
    // given
    int[] tablica = {100, 200, 300};
    int liczba = 300;

    // when
    boolean czyZawiera = czyZawieraElement(tablica, liczba);

    // then
    if (!czyZawiera) {
      System.out.println(
          "Blad! Element 300 powinien byc znaleziony."
      );
    }
  }
}

Testy zapisaliśmy zgodnie z notacją given .. when .. then – najpierw przygotowujemy dane, następnie wywołujemy testowaną metodą i zapisujemy jej wynik, a na końcu sprawdzamy wynik.

Powyższe testy są proste – mogłyby również być zapisane w bardziej zwięzły sposób, na przykład:

public static void czyZawieraElement_zawieraSukanyElementNaKoncu_zwrociTrue() {
  if (!czyZawieraElement(new int[] {100, 200, 300}, 300)) {
    System.out.println(
        "Blad! Element 300 powinien byc znaleziony."
    );
  }
}

Powyższy przykład pomija sekcje "given", "when" oraz "then" i znacząco skraca test – jest on na tyle prosty, że taka postać mogłaby być preferowana, ale w ramach ćwiczenia i przykładu użyta została konwencja given .. when .. then.

Pamiętajmy! Testy powinny być czytelne, ale krótsze testy to mniej kodu do zrozumienia i utrzymania. Należy zawsze zastanowić się czy napisany przez nas kod testu zyskałby na rozbiciu go na sekcje given .. when .. then, czy może lepiej byłoby napisać krótki i prosty test bez używania tej konwencji.

Komentarze (2):

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Nie musisz podawać swojego imienia, e-mailu, ani strony www, aby opublikować komentarz. Komentarze muszą zostać zatwierdzone, aby były widoczne na stronie.