TDD czyli Test Driven Development jest sposobem programowania polegającym na pisaniu najpierw testów. Ponieważ w tym momencie nie ma żadnego kodu, który by ten test mógł przejść, test pada. Programista pisze kod, który obsługuje testowaną funkcjonalność do momentu, w którym test jest wykonywany poprawnie. Następnie albo pisze nowy test i przechodzi do kolejnej funkcjonalności, albo rozwija bieżący test i potem dopieszcza funkcjonalność.

Co to daje? W końcu pisania kodu jest więcej, więc gdzie tutaj usprawnienia?
- Dzięki TDD unikasz ręcznego testowania. Załóżmy sobie dość skomplikowany formularz rejestracji do serwisu. Oprócz standardowych danych (imię, nazwisko, e-mail itp.) zawiera takie pola jak PESEL i NIP. Walidacja danych w tych polach jest dość skomplikowana. Używając TDD piszesz kilka testów na rejestracje użytkownika i zapominamy o sprawie, dopóki testy są wykonywane poprawnie. Jeśli trzeba dołożyć nowe pole, nie ma problemu, najpierw prosta modyfikacja testu, potem dołożenie pola w kodzie. Czasem testowanie ręczne nie jest w ogóle potrzebne.
- TDD wymusza dobrą, modularną architekturę. Wracając do przykładu powyżej, jest pole NIP. NIP może być zapisany w kilku postaciach: PLxxx-xxx-xx-xx, PLxxxxxxxxxx, xxx-xxx-xx-xx, no i oczywiście symbol PL można wymienić na dowolny kraj UE. Teraz, można testować cały formularz i tworzyć użytkowników z różnymi wariacjami NIPu. Albo można napisać krótką funkcję do sprawdzania poprawności samego NIPu i przetestować ją na wielu kombinacjach. Ta druga opcja wymusza modularność kodu – w końcu tę funkcję można skopiować do innego projektu.
- Testy są doskonałą dokumentacją systemu, często o lepszą niż rzeczywista dokumentacja - są po prostu zawsze aktualne.
- Proces projektowania aplikacji z wykorzystaniem TDD pomaga znaleźć ewentualne problemy szybciej. Zmusza programistę do zaprojektowania kodu a dopiero potem pisania, co pozwala uniknąć błędnych decyzji, a jeśli już pojawi się problem, to na tyle wcześnie, że jest jeszcze łatwy do naprawienia.
- Ułatwia współpracę. Programiści mogą bez obaw zmieniać pliki, jeśli coś się popsuje, to testy to wyrażą.
- Ułatwia refaktoring. Znacząco. Powrót do kodu po latach czy nawet miesiącach boli. Jeśli ten kod ma dobre pokrycie testami, to zmiany w nim są o wiele łatwiejsze.
- Za darmo dostajesz testy regresji.
- Wymusza dokładne ustalenie i wyjaśnienie wymagań. W końcu test operuje na konkretnych danych, więc trzeba doprecyzować czy dopuszczamy tylko Polski NIP, czy wszystkie europejskie? A może tylko Polski i Niemiecki?
- Wymusza programowanie iteracyjne. Piszesz test, kod, test, kod….
- Są wspaniałą siatką bezpieczeństwa kiedy trzeba coś w kodzie zmienić — naprawić defekt lub dodać nową funkcjonalność
Test Driven Development nie jest jednak cudownym lekiem na wszystkie problemy – ma też swoje wady.
- Testy kosztują. Pisanie testów na początku powstawania projektu może się wydawać stratą czasu. Rzeczywiście, TDD wydłuża “czas startu”. Jeśli jednak w projekcie zależy Ci na jakości produktu i łatwości jego utrzymania, te początkowe nakłady szybko się zwrócą.
- Wymaga akceptacji całego zespołu. Nie tylko programistów, również managerów. W innym wypadku, mimo posiadania testów na części kodu i tak będzie królowało kosztowne testowanie ręczne, a kod TDD w końcu zostanie usunięty.
- Wymaga nauczenia się nowego podejścia. Testy, zwłaszcza na początku, mogą się wydawać skomplikowane i pisanie ich może być frustrujące.
- Pisanie prostych i szybkich testów wymaga doświadczenia.
- Ciężko jest napisać testy do już istniejącego kodu. Istniejące “potworki” często nie są na tyle modularne, żeby dało się do nich napisać test bez refaktoringu.
- Kod testów również trzeba utrzymywać. Jeśli wymagania produkcyjne się zmieniają, najpierw należy przemyśleć testy. Należy dbać o usuwanie już zbędnych testów. Do tego dochodzą aktualizacje oprogramowania. O kod testów należy dbać tak samo jak o kod produkcyjny.
- Mockowanie. Czasem trzeba napisać sporo kodu, który będzie udawał zewnętrzny serwis (API, bazę danych itp.) które są wykorzystywane w projekcie. To bywa trudne. Na szczęście jako rezultat powstaje biblioteka, którą można wykorzystać w innych projektach.
- Czasami testy mogą być pisane ”dla sztuki”. Dzieje się tak na przykład wtedy, gdy mamy do spełnienia jakąś wydumaną wartość metryki w styku code coverage równe 90%. Takie stawianie sprawy może się skończyć pisaniem testów na najprostsze funkcje, byle tylko podbić wskaźnik.
- Nawiązując do poprzedniego: można wpaść w błędne koło pisania “ładnych” testów, wykorzystywania ciekawych metod i optymalizacji samego frameworka testowego. Proste testy są szybsze do utworzenia i utrzymania niż skomplikowane pętle. Ponadto, moja ulubiona mantra: Done is Better Than Perfect.
Według mnie TDD ma sporo więcej zalet niż wad. Zwłaszcza jeśli projekt ma trochę życia przed sobą. Jednak, jeśli miałbym stworzyć na szybko serwis w stylu POC (proof of concept - udowodnienie pomysłu) darowałbym sobie TDD - to po prostu nie ma sensu kiedy zależy nam bardzo na czasie.
Masz uwagi do posta, chcesz porozmawiać, szukasz pomocy z Pythonem i Django? Napisz do mnie!
Ps. Spodobał Ci się post? Udostępnij go na swoich kanałach.