Wprowadzenie

Obecnie TDD jest jedną z najszybciej rozwiąjących się gałęzi w świecie IT. Większość z nasz porusza się w metodologii Agile szukając sposobu na przetestowanie kodu w ramach istniejącego kodu.

Dlaczego powinniśmy uczyć się TDD? Zanim odpowiemy na to pytanie warto pamiętać o kilku podstawowych rzeczach:

  • nie należy mieszać Unit Test’ów oraz TDD;
  • TDD jest czymś w rodzaju pisania kodu i jednoczesnego testowania;
  • jest testowaniem kodu z poziomu kodu;
  • TDD wymusza, aby napisany kod był przetestowany i poddany refraktoryzacji (zmiany w projekcie, w wyniku których nie zmiania się funkcjonalność).

Po przeczytaniu powyższych punktów nasuwa się pytanie: po co uczyć się takiego podejścia? Wyobraźcie sobie sytuację w której programista przeprowadził testy jednostkowe a tester wykonał swoją pracę – sprawdził produkt i oddał go jako gotowy do sprzedaży. Co się stanie w sytuacji w której zmiana innego programisty doprowadzi do zepsucia kodu pierwszego z nich? W tym miejscu możemy wyjaśnić istotę TDD. Pojęcie to samo w sobie jest definicją. Oznacza, że pisząc kod od razu go testujemy. Jeżeli ktoś uszkodzi Wasz kod wówczas Twój test się nie powiedzie a Ty zaczniesz szukać miejsca wystąpienia błędu. Jest to jeden z aspektów, TDD jest pojęciem ogromnym.


TDD

Zgodnie z definicją wikipedi: jest to proces tworzenia oprogramowania, który opiera się na powtarzaniu bardzo krótkich cykli rozwoju: pierwszy programista pisze (początkowy, zakończony niepowodzeniem) automatyczny przypadek testowy, który określa pożądaną poprawę lub nową funkcję. Następnie wytwarza się minimalną ilość kodu potrzebną do przejścia przez test a następnie cały kod jest refraktoryzowany do akceptowalnych standardów.

Test Driven Development - wprowadzenie

TDD składa się z trzech etapów zwanych Red, Green, Refactor (RGR):

  • Czerwony – pierwszy test, który się nie powiódł;
  • Niebieski – zmodyfikowany/zmieniony kod, który przeszedł test;
  • Refractor – kod poddany refraktoryzacji.


Ćwiczenie

W ćwiczeniu tym posłużymy się podejściem, które pozwala programiście doskonalić swoje umiejętności przez praktykę oraz powtórzenia - Kata.

FizzBuzz Kata

Naszym zadaniem jest wypisanie w konsoli numerów od 1 do 100. Jednakże, dla wielokrotności liczby 3 wypisujemy Fizz a dla wielokrotności 5 wypisujemy Buzz. Jeżeli liczba jest wielokrotnością zarówno 3 jak i 5 wypisujemy FizzBuzz.

Przygotowanie środowiska do pracy:

  • Uruchomić Visual Studio;
  • Utworzyć nowy projekt;
  • Nadać mu nazwę;
  • Dodać dwie klasy: FizzBuzz.cs oraz TestFizzBuzz.cs;
  • Dodać wsparcie NUnit do projektu.
W pierwszej kolejności piszemy prosty algorytm, który pozwala na wypisanie liczb z przedziału 1 – 100:
public string PrintNumber()
{
    string numbers = string.Empty;
    for (int i = 1; i <= 100; i++)
    {
        numbers += " " + i;
    }
    return numbers.Trim();
}
Przystępujemy do pierwszego testu. Nasze ćwiczenie mówi, żeby napisać Fizz jeżeli liczba jest wielokrotnością 3. Dodajemy poniższy test do naszej klasy TestFizzBizz:
[Test]
public void CanReturnFizzIfNumberMultipleByThree()
{
    var numbers = FizzBuzz.PrintNumber();
    // Klasa zawiera kolekcję statycznych metod, które pozwalają na dokonanie porównania
    Assert.True(numbers.Contains("Fizz"));
}
Uruchamiamy powyższy test w Visual Studio. Rezultat:

Test Driven Development - wynik testu

Nasz test się nie powiódł – Poziom Czerwony

Wiemy, że nas test się nie udał i znamy jego powód. W kolejnym kroku poprawiamy kod tak, aby przeszedł test:

public static string PrintNumber()
{
    string numbers = string.Empty;
    for (int i = 1; i <= 100; i++)
    {
        // sprawdzamy czy liczba dzieli się przez 3 bez reszty
        numbers += i % 3 == 0 ? " " + "Fizz" : " " + i;
    }
    return numbers.Trim();
}
Ponownie uruchamiamy ten sam test:

Test Diven Development - wynik działania testu

Tym razem test się powiódł, przechodzimy do kolejnej fazy – Poziom Zielony.

Wracamy do naszego kodu w celu sprawdzenia czy możemy poddać go refraktoryzacji. Możemy dodać metodę do sprawdzania czy liczba dzieli się przez 3 bez reszty:

private static bool IsFizz(int i)
{
    return i % 3 == 0;
}
A tak prezetnuje się wywołanie:
public static string PrintNumber()
{
    string numbers = string.Empty;
    for (int i = 1; i <= 100; i++)
    {
        // sprawdzamy czy liczba dzieli się przez 3 bez reszty
        numbers += IsFizz(i) ? " " + "Fizz" : " " + i;
    }
    return numbers.Trim();
}
Nasz kod został poddany refraktoryzacji, jesteśmy więc na poziomie refraktoryzacji. Teraz należy powtórzyć kroki, aby otrzymać kod zgodny z postawionymi wymaganiami. Pozostałe punkty to:
  • Dla wielokrotności liczby 5 należy wypisać Buzz;
  • Dla wielokrotności liczby 3 i 5 należy wypisać FizzBuzz;
  • A w przeciwnym wypadku liczbę.