Co spodobało mi się w TDD?
Prosta matematyka dziewięć minus trzy daje sześć. I tyle miesięcy nic nie pisałem. Minęło pół roku, i to nawet nie wiem kiedy. W tym czasie sporo pracowałem, rozwijając dwa projekty. Jednym z nich była gra a drugim praca inżynierska. Obie to aplikacje mobilne i obie pisane w Kotlinie. I właśnie podczas prac nad tym drugim, dopadła mnie myśl. A była ona taka:
Opowiedz mi swoją historię
Jako, że testy jednostkowe i tak chciałem zawrzeć w projekcie to uznałem, że ciekawie byłoby skorzystać z wcześniej wymienionej techniki. Sama aplikacja jest już na dość zaawansowanym etapie, ale nadal pozostaje sporo do zrobienia. Testy w modzie, TDD brzmi dumnie, więc wziąłem się do roboty. Trochę testów miałem dodanych, zbyt dużo ich nie było, toteż uznałem, że znajdzie się miejsce na naukę metody TDD przy tworzeniu nowych ficzerów. W żadnym z projektów, w których do tej pory brałem udział, nie korzystałem z TDD. W zasadzie żaden z projektów nie miał testów jednostkowych, więc trudno mówić o TDD :). Same unit testy starałem się pisać w prywatnych projektach, ale nigdy nie usprawniałem tego procesu za pomocą TDD.
Do rzeczy.
Co to w ogóle jest te TDD?
Jest to metoda pisania kodu, która odwraca proces jego wytwarzania. W normalnym sposobie pisania, do którego każdy programista jest przyzwyczajony (no chyba, że korzysta z TDD) , najpierw piszemy kod, a poźniej testy jednostkowe do tego co właśnie dodaliśmy. TDD odwraca to o 180 stopni!
Chcesz dodać metodę, której zadaniem jest dodanie dwóch liczb i zwrócenie wyniku?
Ok, najpierw test, poźniej kod.
Co? No tak, najpierw test, później kod.
OK, ale co ja mam testować? Przecież kodu nie mam! Zaraz go dodasz, spokojnie.
Pisząc najpierw test, zmieniamy sposób myślenia o rozwiązaniu. Myślimy o rezultacie, konkretnym wyniku. Załóżmy, że piszemy kalkulator i mamy do napisania metodę do dodawania dwóch liczb. Zabieramy się do pracy. Mamy pusty plik rozwiązania. W teście sprawdzamy wynik, oczekujemy, że dodając 3 do 2, otrzymamy 5. Piszem test, program się nie kompiluje, test nie przechodzi, więc dodajemy metodę do testowanej klasy, która zwróci nam stałą 5 – test przejdzie. Potem napiszemy kolejny, dodamy 2 do 2, oczekujemy wyniku 4 – test nie przejdzie – dostajemy informację, coś jest nie tak z rozwiązaniem. Ok, w takim razie dodajemy kod odpowiedzialny za dodanie dwóch liczb, które przekażemy jako parametry metody – test przejdzie. Mamy dwa sprawdzone przypadki dla tej metody, nie musimy tego żmudnie debugować. Oszczędzamy czas, jednocześnie dostajemy przetestowany kod.
Jest to bardzo prosty i banalny przykład, ale obrazuje esencje TDD: masz myśleć o rezultacie, a nie implementacji. Odwraca to proces, początkowo jest to bardzo trudne, ale daje wymierne korzyści. Metoda TDD działa wg. schematu

Kolory oznaczają wyniki testów, na początku nie mamy nic, albo posiadamy błędne rozwiązanie – test nie przechodzi. Następnie dodajemy pierwszą, najprostszą implementację – test przechodzi. Refaktoryzujemy kod rozwiązania. Nic nie zepsujemy, o czym od razu się nie dowiemy, bo mamy dodane testy, które powiedzą nam czy niczego nie zepsuliśmy. Najlepsze jest to, że dostajemy testowalny kod. Dlaczego to wiem? Bo napisałem test jednostkowy (Sherlocku!). Pisząc najpierw implementację, a dopiero potem test, może się okazać, że potrzebujemy zmian, aby móc poprawnie przetestować kod. Korzystając z TDD to ryzyko się zmniejsza. A jednocześnie widząc zielony kolor w naszej konsoli, jesteśmy przekonani, że piszemy dobry kod, który działa – dodatkowa motywacja do pracy 🙂
Pierwsze spostrzeżenia
Tak jak napisałem na początku, zanim zacząłem korzystać z TDD miałem już trochę napisane kodu. Naturalnym ruchem było dodanie do niego testów. Powiem szczerze, że trochę nastręczyło mi to trudności. Ciągle miałem w głowie konkretną implementację w już napisanym kodzie, co nastręczało mi problemu z tym, jak mam go przetestować. Z jakiegoś powodu nie mogłem skupić się na tym, co chcę sprawdzić, bo myślałem o tym, z czego składa się testowany kod i jakich zależności używa.
Inaczej sprawa miała się z pisaniem testów do jeszcze nienapisanego kodu. Oczywiście na początku jest bardzo trudno zmienić sposób myślenia, ale przypadki testowe przychodziły jakby same, jakoś naturalniej nie skupiałem się na implementacji, ale właśnie na rezultacie. I test za testem dodawałem kod do projektu, przechodząc przez refaktoryzację i byłem prawie pewny, że nic nie zepsułem po drodze. To ’prawie’ bierze się z niepewności czy moje testy są dobrze napisane. Szczególnie na początku miałem trudność w ocenie poprawności merytorycznej testu, czy wymyśleniu co chcę przetestować. Zaczęło to znikać, kiedy uznałem, że lepszy byle jaki test niż żaden 🙂
Są to moje przemyślenia i odczucia. Z pewnością są osoby, którym może być łatwiej pisać test do już napisanego kodu, ale mimo wszystko zachęcam do sprawdzenia TDD i wyrobienia sobie zdania.
A ja tymczasem wracam do pisania kolejnego testu!
