Nasza strona używa cookies. Dowiedz się więcej o celu ich używania i zmianie ustawień w przeglądarce. Korzystając ze strony, wyrażasz zgodę na używanie cookies, zgodnie z aktualnymi ustawieniami przeglądarki. Rozumiem

Czy nadal kocham TDD?

Denis Lutz Full Stack Developer / HORNBACH Baumarkt AG
Poznaj zalety podejścia TDD i sprawdź, kiedy stosowanie go ma największy sens.
Czy nadal kocham TDD?

Około 3 lata temu po raz pierwszy podszedłem do pracy z TDD i byłem tym bardzo podekscytowany. Wydawało się to bardzo logicznym rozwiązaniem w wielu różnych sytuacjach. Robiłem raz prezentację na ten temat i chciałem podzielić się tym, czego nauczyłem się po stosowaniu podejścia TDD gdziekolwiek mogłem, przez 3 lata.

Oto prezentacja podsumowująca procedurę TDD i teorię wokół niej.

Gdybyś zapytał mnie dzisiaj, czy cała teoria, którą przeczytałem w książkach i pokazałem w prezentacji, nadal ma zastosowanie, odpowiedziałbym: tak... w większości przypadków. Być może najważniejszą rzeczą, o której należy pamiętać, jest zwrot inwestycji (ROI) i właśnie przez ten pryzmat większość kierowników projektów czy architektów chce oceniać przydatność tej metody. To logiczne.

Przyjrzyjmy się najpierw tradycyjnemu modelowi kaskadowemu:

Należy tu wspomnieć, że nie jest to jedyny sposób, w jaki działają projekty, nawet w zwinnym cyklu sprintu. Jest to przepływ pracy, przez który programista przechodzi, pisząc jakąkolwiek małą funkcję. Przykładem może być tu metoda w serwisie, którą programista musiałby napisać w architekturze spring, która konsumuje wstrzykiwane instancje DAO.

Zauważyłeś pozycję "Co?" i "Jak?".

Mógłbyś spytać, co jest takiego specjalnego w tej zmianie przepływu pracy? Co mnie tu tak zainspirowało?

Cóż, dwie rzeczy....


Projektowanie tylko w razie potrzeby

Nie warto rozpoczynać wielkiej procedury, nie wiedząc czy się uda.

Usiądź z młodszym programistą i przeanalizuj, jak podchodzi do problemu, który musi rozwiązać. Jedna ścieżka, którą mógłby obrać, to siedzenie i próba opracowania stosu metod na kawałku papieru, przy użyciu podejścia UML, którego wszyscy nauczyliśmy się w szkole. Jest to typowe zadanie dla architekta, które w rzeczywistości nigdy nie działało.

Innym sposobem jest rozpoczęcie implementacji przy użyciu TDD i projektowanie stosu metod po drodze.

Tak, potrzebujemy dużego projektu architektonicznego na poziomie API systemu i komunikacji REST z innymi systemami. Ale na poziomie kodu trudno jest zobaczyć swój projekt z góry, a nawet nie jest to konieczne. Jest to podstawowa myśl o programowaniu zwinnym, jakiej nauczyłem się tego od Martina Fowlera.

Jak opisuje Martin Fowler w tym artykule, procedura kaskadowa jest predykcyjna i dlatego całkowicie trudna do wykonania, ponieważ chcemy przewidzieć rzeczy i uchwycić ogromny system, który jest bardzo trudny do uchwycenia.

Proces zwinny jest adaptacyjny. Oznacza to, że kierujemy się funkcjami, które posiadamy i projektujemy po drodze, dostosowując je do naszych wymagań, potwierdzając funkcjonalność poprzez testy. Jest to powód, dla którego bez testów nie można wykonać żadnej zwinnej procedury.

Czy Twój menadżer o tym wie? Zapytaj go lub ją, jak definiuje zwinność - oprócz rozwoju oprogramowania w krótkich, dwutygodniowych pętlach.


Test = specyfikacja

To zasada, której wiele osób nie lubiących TDD nie rozumie.

Zapytałbyś, co dla nich oznacza TDD...

"No cóż, to jest podejście, w którym najpierw piszesz test... to dla mnie kompletny nonsens. Skąd mam wiedzieć, jak będzie wyglądał mój kod?"

Tak, to nonsens, jeśli zrobisz to dokładnie tak samo, jak przy wykorzystaniu klasycznego podejścia "test na końcu".

Jak spojrzałem na oświadczenie "test = spec", główną myślą, która przychodziła mi do głowy było to, że "test" jest niewłaściwym słowem do użycia, gdy już używamy TDD. Nie mamy już testu, ponieważ test jest czymś, co można zastosować do czegoś, co już wyprodukowałeś.

Mówimy tutaj o "automatycznie wykonywalnej specyfikacji" naszego kodu. Jest to najważniejszy punkt do zrozumienia i wszystkie inne zasady są niżej w hierarchii istotności:

  • Pisanie testu jako części specyfikacji
  • Skupienie się na jednej konkretnej części systemu w danym czasie
  • Ograniczanie się do jednej części kodu podczas pisania testu, pisanie go od razu poprawnie na świeżo, żeby z biegiem czasu niczego nie zapomnieć.


Teraz przejdźmy do drugiej części tej dyskusji.


Czy TDD jest dla nas wartościowe i czy powinniśmy z niego korzystać?

Podczas gdy większość pracodawców chce, by stosować tę metodę, sądząc nawet po ofertach pracy, to nadal istnieją ludzie, których trzeba w kółko przekonywać do TDD. Dlatego chcę to jeszcze raz przedyskutować.

Istnieją powody, dla których deweloperzy odrzucają istnienie potrzeby stosowania TDD. Sam tak kiedyś miałem.


Deweloperzy po prostu nie rozumieją TDD

Nie lubią tego podejścia. Używają pewnej mieszanki TDD i waterfalla, bez wykorzystania zalet TDD.

Rozwiązaniem jest eksperymentowanie i stosowanie zasad TDD na mniejszych próbkach. Przeczytaj moją prezentację na początku postu. Możesz pracować przez 3 cykle w TDD, zastosować skróty klawiszowe Eclipse do generowania kodu i spróbować zrozumieć, jaką wartość przynosi każdy krok.


Tworzenie konfiguracji testów jest czasochłonne

Jest to największy wróg TDD i ja sam byłem jego ofiarą kilka razy.

To, z czym się tu najczęściej mierzymy, to skomplikowana domena biznesowa, połączona ze żmudną do zrobienia konfiguracją fixture'ów. Powodem tego jest zazwyczaj zły wybór technologii i źle zorganizowane środowisko do fixture'ów.

Lider techniczny projektu powinien dbać o czas zainwestowany w tworzenie konfiguracji do testów. W razie potrzeby dedykowana osoba powinna otrzymać zadanie stworzenia łatwego do zrobienia setupu do testów oraz testowej bazy danych.

Oto niektóre z krytycznych pytań, które wg mnie musisz sobie zadać i rozwiązania, które się z nimi wiążą:

1. Czy posiadasz tekstowe fixture'y wspomagane przez DSL? Jak XML, CSV lub YAML (Rails)?

Jeśli nie, to nie oczekuj, że zespół osiągnie dobre pokrycie testami. Na starcie jesteś na przegranej pozycji. Tak, dobry programista może przetrwać z ograniczonym testowaniem. Ja również z takimi pracowałem. Jak wiesz, każdy kod w końcu się komplikuje, więc Twoim celem jest uczynienie go jak najprostszym i jak najbardziej produktywnym. To jest Twoja przewaga przed konkurencją.

Wracając do fixture'ów, ogromna poprawa przychodzi zazwyczaj poprzez ustanowienie API do tworzenia fixture'ów. To właśnie to ogromnie pomogło mi osiągnąć dobre pokrycie testowe w kilku projektach.

Zmiany w społeczności Javy i Rails są na to bardzo mocnym dowodem:

  • Termin "POJOs" w języku Java, to obiekty które można łatwo tworzyć w dowolnym środowisku testowym.
  • Biblioteki Ruby, takie jak factory girl , API do tworzenia obiektów do testów.


A przy okazji, tworząc obiekty z poziomu kodu, a nie za pomocą fixture'ów, zdecydowanie zmuszasz programistów do uproszczenia procesu tworzenia obiektów. Natychmiast tworzysz dwóch klientów swojego kodu. Test i kod, w którym będziesz używał swoich obiektów.

2. Czy oprócz fixture'ów, ogólne tworzenie testu jest łatwe? Jak dużo wiedzy potrzebujesz, by stworzyć test?

Ostatnią rzeczą, o której wspomnę, jest zwrot z inwestycji. Zasada ta ma zastosowanie w każdym środowisku testowym. Nie ma znaczenia, czy test jest łatwy, czy trudny do stworzenia. Właśnie to powinno decydować w każdej sytuacji, czy opłaca się stosować TDD.

Potencjalnie możesz sprawdzić każdą nową metodę kodu za pomocą testu, aby było to zgodne z zasadami TDD. Ale nie zawsze jest to najlepszy wybór.

To, na co powinieneś się zdecydować, to oczywiście najwyższy zwrot z inwestycji, czyli osiągnięcie jak największej wartości w teście, poprzez zainwestowanie jak najmniejszej ilości czasu.

Sam przekonałem się, że to, co nazywam "podstawowym wykonaniem kodu" jako test i podstawowe zapewnienie, wnosi już ogromną wartość. Tak właśnie postrzegałem zysk TDD, stosując tylko tę zasadę.

Czy kiedykolwiek słyszałeś takie stwierdzenie, że lepiej jest mieć jakiekolwiek testy, niż nie mieć ich w ogóle? Idzie to w parze z tym doświadczeniem i jest to absolutna prawda. Uważam, że osiągniesz ponad 50% możliwych zysków z testów, przez samo wykonywanie kodu.


Co daje Ci podstawowe wykonanie kodu?

  • Testowanie konfiguracji bean w architekturze frameworku spring.
  • Niebezpośrednie testowanie obszarów kodu pod kątem obsługi nowych funkcji.
  • Projektowanie API tak, jak chciałbyś, żeby wyglądały od początku.
  • Skupienie się na jednej części kodu zamiast rozpoczynania sesji debugowania w stosie metod.
  • Testowanie kontrolera w środowisku Rails renderuje i testuje wraz z nim również widok.Tak więc należy zastosować minimalną ilość pracy i uzyskać z niej jak największą wartość.


Podsumowanie

To są moje ogólne myśli na temat TDD po długim czasie korzystania z niego. To wciąż świetna koncepcja. Uwielbiam ją stosować i mogę ją tylko polecać wszystkim innym.


Oryginał tekstu w języku angielskim przeczytasz tutaj.

Masz coś do powiedzenia?

Podziel się tym z 120 tysiącami naszych czytelników

Dowiedz się więcej
Rocket dog