Przykład tworzenia kodu z wykorzystaniem podejścia TDD:
Cykl pierwszy RED–GREEN–REFACTOR:
Faza RED: piszę minimum kodu testu aby test był failujący. Błąd kompilacji to również failujący test. Klasa GameRepository jeszcze nie istnieje, test nie przechodzi. Faza GREEN: piszę minimum kodu aby test przeszedł. Wystarczy utworzyć brakującą klasę. Test przechodzi.Faza REFACTOR: brak kodu do refaktoryzowania po tym cyklu.
Powtarzam cykl – cykl drugi:
Kontynuję pisanie testu. Dodaję w sekcji //given kolejny obiekt nieistniejącej jeszcze klasy Game. Test nie przechodzi.Tworzę klasę Game z wymaganami polami oraz konstruktorem. Test przechodzi.Brak kodu do refaktoryzowania po tym cyklu.
Cykl trzeci:
W teście tworzę sekcję //when i dodaję wywołanie metody .add() na obiekcie klasy GameRepository. W tej klasie nie istnieje jeszcze taka metoda dlatego test nie przechodzi.W klasie GameRepository dodaję sygnaturę metody add(). Test przechodzi.Brak kodu do refaktoryzowania po tym cyklu.
Cykl czwarty:
Tworzę sekcję //then i dodaję w niej asercję korzystającą z nieistniejącej jeszcze metody klasy GameRepository .getAllGames(). Test nie przechodzi.W klasie GameRepository dodaję metodę getAllGames() zwracjącą listę wszystkich gier dodanych do repozytorium oraz uzupełniam o logikę dodaną wcześniej sygnaturę metody .add(Game game) dodającą grę (obiekt klasy Game) do repozytorium. Test przechodzi.Uzupełniam logikę asercji aby otrzymać spodziewany efekt metody testowej.Brak kodu do refaktoryzowania po tym cyklu.
Cykl piąty:
Tworzę nowy test. Próba wywołania nieistniejącej metody .remove() powoduje błąd kompilacji – test nie przechodzi. W klasie GameRepository tworzę sygnaturę brakującej metody remove(). Test przechodzi.Refactor: z obu metod testowych przenoszę powielony kod tworzenia instancji obiektu klasy GameRepository poza metody testujące, jako pole klasy testowej.
Dzięki takiemu podejściu tworzymy dokładnie tyle kodu ile jest wymagane do zamierzonego działania aplikacji. Mamy kontrole nad tym ile kodu powstaje w zależności od wymagań niezbędnych do spełnienia.
Przedstawiony przykład prezentował tworzenie nowych funkcjonalności i testów. Kiedy mamy do czynienia z legacy codem i naprawą bugów, cykl zacznym od testu reprodukującego danego buga.