TDD Test Driven Development: By Example

TDD zaczyna od końca

Opis systemu zaczyna się od opisywania funkcji które oferuje.
Opis funkcji zaczyna się od opisania pożądanego stanu którym skutkuje wywołanie funkcji.
Implementacje zaczyna się od napisania testów które wykorzystują tą implementacje.
Testy zaczyna się od pisania asercji która weryfikuje czy test przeszedł.

Cykl TDD

  • napisanie testu który nie przechodzi
  • napisanie kodu który przechodzi test jak najprostszym sposobem
  • refactor

Test nie przechodzi

Pierwsza część cyklu sprawdza założenia (być może warunek będzie już spełniony np. przez wykorzystywaną bibliotekę).
Istotne jest żeby być jak najkrócej w „CZERWONYM” etapie. To sprawia że skomplikowany problem jest rozbijany na mniejsze fragmenty o których łatwiej myśleć.
Istotna jest umiejętność robienia zmian w wielu krokach by utrzymać powyższy cykl. Jeśli coś jest oczywiste można skumulować kilka zmian ale jeśli testy nie przechodzą należy wrócić do małych kroków.
Zmniejszanie „CZERWONEGO” etapu skutukuje szybszą informacją czy poprzednia decyzja (najlepiej jedna) była słuszna.

Banalna implementacja

Druga część cyklu sprawdza zasadność testu – wyklucza pisanie skomplikowanej implementacji czegoś niepotrzebnego/błędnego. Jest to realizowane przez:

  • napisanie kodu który hardcoduje pożądaną wartość (Fake)
  • zaimplmentowanie oczywistego rozwiązania (Obvious Implementation)

Refactor

Trzecia wprowadza porządek. Wraz z dopisywaniem testów implementacja staje się coraz bardziej ogólna.
Jeśli kod dalej jest tylko sumą różnych przypadków może pomóc triangulacja czyli napisanie testów dla różnych danych (nie koniecznie skrajnych). To może uwidocznić algorytm do zaimplementowania.

Zbyt silne powiązanie testów z implementacją jest złe. Musi być możliwość dopisywania kolejnych testów bez zmiany kodu źródłowego.

Kolejny cykl

Należy zajmować się tylko jednym zagadnieniem na raz a pozostałe spisywać. Ze spisanych najlepiej wybierać te które wydają się proste do zrobienia (ale nie koniecznie te najprostsze – te nic nie wniosą).
Jeśli już praca nad zagadnieniem jest przerwana czymś pobocznym nie należy przerywać przerwania.
TDD i YAGNI są bardzo blisko związane. Nie należy pisać czegoś do czego nie ma testów a nie należy pisać testów do czegoś co nie jest wymagane w tym momencie.
Nowe funkcje można dodawać tylko w „ZIELONYM” etapie (żeby pracować tylko nad jedną rzeczą na raz).

Ogólne

TDD sprawia, że architektura jest dopasowana do aktualnych, nie przyszłych, wymagań.
Wątpliwości trzeba wyrażać w formie testu.
Zaczynać pisanie testów od przypadku który nie wymaga żadnego działania (zdegenerowany przypadek) lub dla najprostszych wariantów.

Dobrze pisać testy służące do nauki zewnętrznej biblioteki. Jak za długo nie ma postępu to zacznij od nowa.
Dobrze zostawiać czerwony test na następny dzień – będzie wiadomo od czego zacząć.

Źródła:
„Test Driven Development: By Example” Wydanie I Kent Beck