Welkom! (holenderski)

Witam Cię w poniedziałkowy wieczór znów na mojej stronie. Tak szybko kolejny wpis? Tak! Nadrabiamy zaległości, poza tym dzisiejszy temat jest kontynuacją wczorajszego, więc idę za ciosem. Dzisiejszy dzień jest bardzo ważny dla mnie z różnych powodów i zwieńczenie go wpisem, będzie wisienką na torcie. Może zastanawiasz się, co z projektem? Te posty są bezpośrednio z nim związane. Otóż jak pisałem, bodajże w opisie projektu na stronie konkursu, wybrałem stosunkowo prosty projekt po to, żeby móc pokazać troszkę wiedzy i poglądów na pewne tematy oraz nauczyć się nowych technologii na jakimś żywym przykładzie. Także w projekcie dzieje się cały czas! No ale już nie przedłużając, jedziemy z dzisiejszym tematem.

Dzisiaj chcę z Tobą, drogi czytelniku, pociągnąć temat zwinności i metodyk z nią związanych. Jeżeli widziałeś ten szkic specyfikacji, który powstał i leży sobie spokojnie na GitHub, to może zwróciłeś uwagę na końcowe zdanie. Do budowy aplikacji zostanie wykorzystana metodyka Test-Driven Development. Ale co to tak naprawdę jest?

TDD

TDD, czyli Test-Driven Development jest uważana za metodykę zwinną głównie ze względu na spełnienie manifestu: “Działające oprogramowanie ponad obszerną dokumentację”. Testowanie oprogramowania ogranicza (nie eliminuje!!!) występowanie błędów, a dobrze napisane testy mogą usprawnić dokumentowanie kodu, możemy potraktować je jako formę specyfikacji. Wróćmy do początku i zdefiniujmy sobie dokładnie hasło TDD. Za tym pojęciem kryje się cykliczne wykonywanie kilku kroków (za Wikipedią):

  1. Projektujemy test
  2. Implementujemy funkcjonalność
  3. Refaktoryzujemy kod

Brzmi to jednak bardzo pobieżnie i enigmatycznie, jednak kryje się za tym bardzo duża siła (czym jestem ostatnio zafascynowany i dlatego teraz, razem z Wami poznaję tę tematykę).

Co w trawie (TDD) piszczy?

Sednem TDD nie jest tak naprawdę pisanie oprogramowania niejako od tyłu, no bo w sumie po co i czemu tak, a w ogóle to te całe testy to nie wiadomo po co są, szkoda klawiatury. Pozwól jednak, że udowodnię Ci nieprawdziwość takiego podejścia!

Z definicji test jednostkowy ma przetestować pojedynczy element programu, jego zachowanie w różnych, mniej lub bardziej sprzyjających warunkach. Rozpoczynanie tworzenia aplikacji od zdefiniowania testów, które nawet się nie skompilują ze względu na brak reszty szkieletu zmusi do myślenia i wyciągnięcia z odchłani mózgu, co tak naprawdę chcemy uzyskać. Wychodzimy ze sztywnych więzów implementacyjnych na rzecz interfejsu i funkcjonalności, co w sumie jest zgodne z Agile (znów).

W kolejnym kroku następuje implementacja brakującego szkieletu (z tego co się orientuję to VS i Eclipse udostępniają automatyczne narzędzia, trzeba się będzie przekonać :), ponadto w tym kroku solucja się skompiluje ale uruchomienie wywoła test, które siłą rzeczy nie przejdą) i wypełnienie tego szkieletu logiką (o i działa :D). W tym miejscu zaczynają przechodzić testy. Przechodzimy zatem do punktu 3., czyli refaktoryzujemy kod. Ta wstępna implementacja jest pisana tak z marszu, po to, żeby testy przeszły. Osiągamy przez to jeden cel działającej funkcjonalności spełniającej nasze oczekiwania. Refaktoryzacja jest bardzo ważnym krokiem. Otóż kod powinien być sporządzony w taki sposób, aby testy zawsze kończyły się wynikiem pozytywnym, zatem refaktoryzacja kodu nie ma prawa wpływać na wynik testu. Jeżeli tak jest, to należy się zastanowić, czy sam test został sporządzony poprawnie (znaczyłoby to, że funkcjonalność jako taka nie została dobrze określona). W przeciwnym razie popełniliśmy błąd w przebudowie kodu i należy przeprowadzić ten proces jeszcze raz.

Refleksja

Czy warto jest stosować TDD? Tak! Jednak jak ze wszystkim musimy być rozważni. Już tłumaczę w czym rzecz. Takie podejście do stworzenia oprogramowania pozwala na minimalizację liczby błędów występujących w tworzonym oprogramowaniu. Nigdy nie jesteśmy w stanie wyeliminować ich w 100%, ale minimum jest zawsze najlepszą opcją 🙂 Ponadto testy stanowią dokumentację funkcjonalności dostarczanych przez pakiet oraz mają w sobie przykłady użycia – zatem bezsensowne staje się pisanie zewnętrznego manuala jako dokumentu, jeżeli śledząc kod testu możemy tego dotknąć na żywca.

Oczywiście też jest druga strona medalu. Testy są oczywiście kodem do utrzymywania – dla części osób może to stanowić poważny problem, bo jak wiemy programista to z natury leniwe coś. Samo podejście od tej strony nie jest łatwe, jednak wszystko się da. Materiałów jest cała masa, czy to właśnie podobnych dywagacji czy tutoriali. Pod postem coś tam podlinkujemy fajnego 🙂 To chyba tyle, pamiętaj też, drogi czytelniku, że to tylko narzędzie i trzeba z niego odpowiednio korzystać 🙂

Nie samym TDD człowiek żyje

To co, tak zachwalał i tłumaczył i teraz ucieka? Nic z tych rzeczy 🙂 Ale przy tak świetnej okazji trzeba wspomnieć o ewolucji narzędzia TDD, znanej jako Behavior-Driven Development, w skrócie BDD. Szukając w internecie informacji na ten temat przygotowując się do tworzenia tego posta, często spotkałem się ze stwierdzeniem, że BDD to TDD a TDD to BDD. W istocie rzeczywiście tak jest. Rozszerzenie BDD względem TDD polega na wykorzystywaniu narzędzi do definiowania funkcjonalności oraz przygotowywaniu tzw. user scenarios, które to opisują przebieg krok po kroku konkretnej funkcjonalności. Świetny przykład formowania user scenarios znajduje się pod tym linkiem. User scenarios zapisuje się np. za pomocą języka Gherkin, który współpracuje z narzędziami wspierającymi BDD, np. Cucumber, z którego ja będę korzystał, ale to już w kolejnym poście. BDD też można określić jako metodykę nie będącą tak bardzo restrykcyjną jak TDD. Jednak ta różnica jest jak mówiłem bardzo nikła. Wikipedia angielska mówi: “Behavior-driven development combines the general techniques and principles of TDD with ideas from domain-driven design and object-oriented analysis and design to provide software development and management teams with shared tools and a shared process to collaborate on software development.”. Myślę, że lepszej konkluzji się nie znajdzie 🙂

Podsumowanie

I tak o to po raz kolejny z wieczora zrobiła się już w sumie noc. Znów post zamiast krótkiego, będzie miał ok. 1000 słów. Mam nadzieję, że w takim telegraficznym skrócie opisałem Ci, co to jest TDD i BDD oraz dlaczego są one takie przyjemne. W kolejnym poście już popracujemy bezpośrednio nad aplikacją, ale musiałem zrobić ten wstęp, by zachować jakiś porządek logiczny 🙂 Mam nadzieję, że Ci się podobało! Zachęcam do komentowania i poprawiania mnie, jeżeli się mylę 🙂 Chciałem także podziękować mojemu koledze Michałowi, który podesłał mi parę linków i zainspirował do pogrzebania na ten temat 🙂 Dziękuję! 🙂 Tymczasem mówię Ci do zobaczenia, ale przewiń stronę dalej, by poklikać w przydatne linki 🙂 Miłego czytania! 🙂

Przydatne linki

TDD Wikipedia: https://pl.wikipedia.org/wiki/Test-driven_development

O testach na Devstyle.pl: http://devstyle.pl/category/tech/tests/

O TDD u Arkadiusza Benedykta: http://www.benedykt.net/2010/11/07/tdd-czyli-test-driven-development/

BDD Wikipedia: https://en.wikipedia.org/wiki/Behavior-driven_development

Narzędzie Cucumber: https://cucumber.io/

Inne:

http://softwareengineering.stackexchange.com/questions/135218/what-is-the-difference-between-writing-test-cases-for-bdd-and-tdd

http://softwareengineering.stackexchange.com/questions/111837/relation-between-bdd-and-tdd

A może…?

Dziękuję Ci, że dotartłeś aż do tego miejsca. Mam nadzieję, że podobał Ci się mój wpis i dowiedziałeś się z niego czegoś wartościowego. Jeżeli chcesz być poinformowanym o moich kolejnych wpisach bądź od czasu do czasu dostać wiadomość ze zbiorem jakiś ciekawych linków, zapisz się proszę do mojego newslettera. Będzie mi niesamowicie miło, jeśli to zrobisz i dołączysz do mojej społeczności!


Piotr Wachulec

Student, konsultant IT/programista, bloger, w wolnych chwilach uczy się nowych rzeczy, tańczy bachatę lub pije pyszną kawę ze znajomymi (chętnie się jej napije także z Tobą! :)). Często można go spotkać na konferencjach, meetupach lub po prostu biegnącego po stolicy na tramwaj. Jego piątka w "teście" Gallupa: Learner, Achiver, Intellection, Relator, Harmony.