Test Driven Development  Udostępnij na: Facebook

Autor: Arkadiusz Benedykt

Opublikowano: 2011-07-08

Szybki rozwój technologiczny oraz dynamicznie zmieniające się wymagania rynku powodują, że dzisiejszy programista powinien być Agile – zwinny, giętki ogólnie elastyczny. Na tej fali powstało wiele metodologii, które mają na celu szybsze dostarczanie produktu do klienta. Bez względu na to, czy te metodologie są skuteczne, czy nie, mają jedną wspólną wadę – wymagają zmiany sposobu pracy całego zespołu. Czy możliwe jest prowadzenie projektu, gdzie połowa zespołu korzysta z dobrodziejstw SCRUM-a, a druga połowa nie? Wątpliwe. Jest jednak pewna „gwiazda” zaliczana do metodyk zwinnych, która może być stosowana zarówno przez pojedynczych deweloperów, jak i przez całe zespoły. Jest nią Test Driven Development (TDD). Niniejszy artykuł pokaże, czym jest TDD, kiedy opłaca się go stosować, a kiedy nie. W kolejnych artykułach skupimy się na tworzeniu aplikacji za pomocą TDD oraz spróbujemy przetestować kod nietestowalny (na pierwszy rzut oka).

Co to jest Test Driven Development

Test Driven Development, czyli TDD, to technika tworzenia oprogramowania sterowana przez testy. Tworzenie kodu składa się z wielokrotnie wykonywanych trzech głównych kroków:

  1. Stworzenie testu jednostkowego, który powinien być możliwie najprostszy, aby uniknąć możliwości popełnienia błędu w samym teście. Test ma sprawdzać funkcjonalność, która będzie implementowana w kroku 2.
  2. Implementacja funkcjonalności – tworzymy funkcjonalność, którą chcemy zaimplementować. Funkcjonalność ta powinna spełniać założenia testu jednostkowego, a wykonanie testu jednostkowego powinno kończyć się sukcesem.
  3. Refaktoryzacja, czyli porządki w stworzonej funkcjonalności. Ma to na celu uporządkowanie kodu, tak aby spełnione były standardy. Czynności wykonywane w tym kroku nie mogą zmienić wyniku testów.

Szczegóły TDD

Pierwszy krok to przygotowanie takiego testu, który będzie testował funkcjonalność, którą będziemy dopiero tworzyć. To daje czas na przemyślenie interfejsu tej funkcjonalności oraz pozwala skupić się nad tym, czego tak naprawdę oczekujemy od implementowanej później funkcjonalności. Czas poświęcony na tworzenie testu skutecznie zmusza programistę do sprecyzowania problemu, z jakim ma się zmierzyć.

Drugi krok to implementacja funkcjonalności. Dopiero mając test, przechodzimy do implementacji funkcjonalności. Co ważne, wprowadzane zmiany nie mogą naruszać innych testów, dzięki czemu mamy pewność, że nowo tworzona funkcjonalność nie zaburza tej już istniejącej.

Trzeci krok to refaktoryzacja, czyli uporządkowanie kodu, doprowadzenie go do stanu zgodnego ze standardami dobrego kodowania. Zmiany wprowadzane podczas refaktoryzacji nie mogę powodować błędów w wykonaniu zarówno testu jednostkowego z pierwszego kroku, jak i tych, które powstały wcześniej. Jest to pierwszy etap, na którym testy jednostkowe zaczynają pokazywać swoją potęgę – jeżeli jakakolwiek zmiana wprowadzona w kodzie powoduje, że jeden lub więcej testów przestaje działać, to wprowadzona zmiana najprawdopodobniej generuje błąd.

Wady Test Driven Development

Metodologia TDD posiada jednak dwie główne wady – wymaga dodatkowego czasu na stworzenie testów jednostkowych oraz wymaga czasu w na utrzymanie testów.

Pierwsza wada może być bardzo zniechęcająca dla kierownictwa, szczególnie w początkowym okresie korzystania z TDD, kiedy deweloper potrzebuje czasem nawet do 30% więcej czasu na wykonanie tych samych zadań. Z czasem jednak, po nabraniu płynności w pisaniu testów, ten dodatkowy czas zmniejsza się, dzięki czemu koszt stosowania tej metodologii maleje.

Druga wada wynika z faktu, że aby testy były użyteczne, muszą być odpowiednio zarządzane i uaktualniane wraz ze zmianami logiki aplikacji. Dopóki dodajemy nową funkcjonalność, problem ten praktycznie nie istnieje, jednak przy wprowadzaniu zmian w istniejącej funkcjonalności należy pamiętać, że potrzebny jest czas na odpowiednie zmodyfikowanie istniejących testów jednostkowych.

Zalety Test Driven Development

Podstawową zaletą TDD jest szybkie wychwytywanie błędów. Już w momencie tworzenia oprogramowania wiele błędów można wychwycić za pomocą tej metodologii. Nie jest to bez znaczenia, ponieważ każdy błąd z czasem „nabiera wartości” – im później błąd zostanie wykryty, tym więcej osób angażuje i tym więcej kosztuje zarówno w aspekcie czasu, jak i pieniędzy. Dlatego chcemy, aby wszystkie błędy były wychwytywane możliwie najszybciej i jak najbliżej programisty. Wystarczy sobie uzmysłowić, ile czasu potrzebujemy, aby poprawić błąd, który zrobiliśmy 5 minut wcześniej, a ile czasu potrzebujemy na poprawienie błędu sprzed 30 dni.

Błędy wykryte przez autora kodu i poprawiane na bieżąco kosztują niewiele, ponieważ angażują tylko jedną osobę. Błędy wykryte przez zespół QA angażuje już czas zarówno programisty, jak i testera (lub testerów), co znacząco podwyższa koszty. A jak takie koszty wyglądają, gdy błąd dotrze do klienta?

Kolejną zaletą TDD jest bardziej przemyślany kod. Ponieważ w pierwszym kroku tworzony jest kod, który będzie wykorzystywał tworzoną funkcjonalność (test), to zazwyczaj naturalnie ten kod jest bardzo prosty i elegancki. Tak stworzony test wymaga, aby tworzona klasa była schludna i prosta do wykorzystania. Jest to efekt, który bardzo łatwo się osiąga – bez dodatkowego nakładu pracy – a przy okazji bardzo cenny szczególnie dla początkujących programistów.

Największą chyba zaletą tej metodologii pracy jest możliwość przetestowania funkcjonalności bez uruchamiania całego oprogramowania – tworzony kod można uruchamiać częściowo, bez uruchamiania całej aplikacji. Nie ma to szczególnego znaczenia w małych projektach, ale już przy średnich i dużych czas jest niezwykle istotny. Za pomocą kilku kliknięć myszy, nie wychodząc z ulubionego środowiska programistycznego, można uruchomić części aplikacji i otrzymać miarodajne wyniki – bez żmudnego uruchamiania kodu, bez męczącego „przeklikiwania” aplikacji i bez tracenia czasu na ponowne koncentrowanie się na istotnym problemie. Test jednostkowy pozwala w ciągu kilku sekund odpowiedzieć na pytanie, czy dany kawałek kodu będzie działał tak, jak chciał tego programista.

Ostatnia, choć nie jedyna, bardzo ciekawa zaleta TDD to tworzenie swoistej dokumentacji. Ile razy zdarzyło się, że nie wiadomo, jak skorzystać z biblioteki rozwijanej przez kolegów i koleżanki? Wiadome jest, że programiści lubią i piszą najlepsze dokumentacje, więc….. wystarczy sięgnąć do testów jednostkowych i poszukać takiego testu, który pokaże nam jak użyć owej biblioteki.

Kiedy stosować TDD?

Chciałoby się powiedzieć – zawsze. Praktyka jednak pokazuje, że nie ma sensu korzystać z TDD w przypadku krótkich, kilkulinijkowych projektów. W takiej sytuacji nadmiarowość czasu jest po prostu zbyt duża. Nie ma również większego sensu korzystanie z tej metodologii w przypadku aplikacji (dalej, kilkulinijkowych), które nigdy nie będą rozwijane.

Powyższe ma zastosowanie praktycznie w małych, próbnych aplikacjach/szkieletach. W codziennej pracy okazuje się, że praktycznie każdy projekt warto rozwijać za pomocą TDD.

Rozwijać – ponieważ generalną zasadą TDD jest pisanie testów jednostkowych przed tworzeniem właściwego kodu. Jak pokazuje praktyka, nie ma większego sensu tworzenie testów jednostkowych do istniejącego kodu (jakość takich testów zazwyczaj jest bardzo niska), zatem pozostaje w istniejących projektach tworzenie testów jednostkowych do nowej funkcjonalności oraz korzystanie z pełni dobrodziejstw Test Driven Development w nowych projektach.