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.
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:
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:
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 prezentuje 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ę.