W jednym z ostatnich wpisów na blogu poruszałem zagadnienia związane z testowaniem oprogramowania. Jednym z zagadnień, które pominąłem w tamtym artykule było podejście, Test Driven Development, w skrócie TDD. Do przykładów wykorzystałem bibliotekę Mocha oraz TypeScripta.
Geneza Test Driven Development
Myślę, że dobrym punktem startu będzie nakreślenie rysu historycznego. Wbrew pozorom sama idea TDD jest starsza, niż mogłoby się początkowo wydawać. Pierwsze wzmianki o technice noszącej znamiona TDD możemy znaleźć w bardzo starych książkach traktujący o programowaniu takich jak “Digital Computer Programming” z 1957 roku. Wzmiankę o czymś na wzór TDD możemy także znaleźć w raporcie z konferencji sponsorowanej przez Komitet Naukowy NATO z 1968 roku.
A software system can best be designed if the testing is interlaced with the designing instead of being used after the design.
Niemniej jednak wtedy nie nosiło to miana Test Driven Development. Termin TDD został spopularyzowany przez 2 książki autorstwa Kenta Becka:
- Extreme Programming Explained: Embrace Change z 1999 roku;
- Test Driven Development: By Example z 2000 roku.
Obecnie termin ten jest tak popularny, że natknąłem się w sieci nawet na kursy, warsztaty i szkolenia skupiające się na temacie TDD. Co ciekawe, niektóre z nich potrafią kosztować naprawdę spore pieniądze.
Czym jest TDD?
Opowiadanie o historii TDD bez wytłumaczenia, na czym ono polega, byłoby niewybaczalnym faux-pas z mojej strony, także szybko naprawiam ten błąd. W skrócie Test Driven Development jest to technika wytwarzania oprogramowania, w której najpierw tworzymy test. Dopiero potem tworzy się kod sprawiający, że test przejdzie pomyślnie. Procedura wytwarzania kodu metodą TDD składa się z trzech etapów — red, green oraz refactor.
Red — na samym początku tworzony jest test. Na przykład dla kalkulatora mógłby to być test dodawania. Rzeczą oczywistą jest, że uruchomienie takiego testu da wynik negatywny. W końcu test sprawdza nieistniejący kod. Dla wspomnianego kalkulatora test mógłby wyglądać następująco.
import { expect } from 'chai';
import SimpleCalculator from '../src/SimpleCalculator';
describe( 'SimpleCalculator - Unit tests' () => {
let calculator: SimpleCalculator;
before( () => {
calculator = new SimpleCalculator();
} );
describe( 'add()', () => {
it( 'should add two numbers and return a correct result', () => {
expect( calculator.add( 2, 2 ) ).to.eql( 4 );
} );
} );
} );
Green — w tej fazie do istniejącego testu wytwarzany kod, który sprawi, że test przejdzie pomyślnie.
export default class SimpleCalculator {
public add( a: number, b: number ): number {
return a + b;
}
}
Jak możesz zauważyć, brakuje tutaj innych metod, których można by się spodziewać w kalkulatorze. Jest to zabieg celowy. Istotne jest to, aby NIE pisać kodu, którego użyteczność wykracza poza wcześniej napisany test. W tej fazie nie jest istotna wydajność ani elegancja kodu. Jedynym jego zadaniem jest sprawienie, aby test przeszedł pomyślnie.
Refactor — faza refaktoryzacji. W tej fazie można zoptymalizować i usprawnić wcześniej wspomniany kod. Wciąż nie należy zapominać o wcześniej wspomnianej zasadzie — nie należy wykraczać poza to, co obejmuje test. Kod z przykładu jest na tyle prosty, że fazę refactor w tym przypadku można pominąć. Po ukończeniu cyklu możemy rozpocząć kolejną iterację poprzez napisanie testu na przykład dla odejmowania. Cykl ten powinien być powtarzany tak długo, aż uzyskamy finalną aplikację.
Zalety i wady TDD
Niewątpliwą zaletą TDD jest możliwość wczesnej detekcji i eliminacji błędów. Oprócz tego mając już zestaw testów, które przeszły przez 3 fazy, zwiększa się odporność systemu na regresję. Jeżeli w fazie green uruchomiony kod spowoduje porażkę innego testu, to jest to oczywisty dowód na powstanie regresji w kodzie.
Kolejnym benefitem jest to, że zgodnie z TDD każda linijka kodu, który został dodany, jest przetestowana, co daje pokrycie kodu na poziomie 100%. Oczywiście do sprawdzenia pokrycia kodu możemy użyć narzędzi tj. Istanbul, ale TDD również nam to zapewnia. Warto pamiętać, że dla biznesu 100% code coverage może być ważnym czynnikiem, a niekiedy kartą przetargową przy pozyskiwaniu klientów. To, czy ma to sens, to już inna para kaloszy 😉
Korzystanie z TDD zwiększa świadomość programisty, nad tym co tworzy oraz jak działa projektowany system. Zaczynanie programowania od testów daje szerszą perspektywę nie tylko na wartość biznesową, którą ma dawać tworzony kod, ale też na architekturę projektowanego systemu.
TDD pozwala również skupić się na jakości i użyteczności publicznego interfejsu tworzonego kodu. Zaczynając od testów, programista musi przemyśleć, jak powinien wyglądać interfejs kodu docelowego.
Jeśli chodzi o wady TDD, to dla początkujących pisanie testu do nieistniejącego kodu, może stanowić wyzwanie. Niemniej jednak po kilku napisanych testach w podejściu TDD nie powinno to stanowić większego problemu. Trudne może okazać się ciągłe pamiętanie, żeby nie dopisywać więcej kodu, niż jest to potrzebne. Pracując w podjeściu TDD, sam bardzo często się na tym łapałem.
Warto też pamiętać, że TDD to nie jest jedyna słuszna droga, tylko narzędzie mające pomóc programiście. Jeżeli czujesz, że TDD nie jest dla Ciebie, to nie jest to nic złego. Nie ma co się zmuszać, nic na siłę.
Podsumowanie
Bardzo jestem ciekaw czy miałeś/aś już styczność z TDD, a jeśli tak to, co o nim sądzisz. Zachęcam do pozostawienia komentarza. Sam osobiście nie programuję zbyt często w podejściu TDD, jednak w trakcie pisania tego artykułu uznałem, że być może warto to zmienić! Jak zwykle zachęcam też do zapoznania się z materiałami dodatkowymi i źródłami.
Szczególnie gorąco zachęcam do sprawdzenia pozycji Kenta Becka — TDD. Sztuka tworzenia dobrego kodu (TDD By Example), która moim zdaniem stanowi pozycję numer jeden, wśród pozycji opisujących pracę w podejściu TDD.
Źródła i materiały dodatkowe
- Metodyki zwinne wytwarzania oprogramowania
- Kent Beck – TDD. Sztuka tworzenia dobrego kodu
- Kent Beck – Extreme Programming Explained: Embrace Change
- The Humble Programmer
- Software Engineering Report on a conference sponsored by the NATO Science Committee
- You won’t believe how old TDD is
- Why does Kent Beck refer to the „rediscovery” of test-driven development? What’s the history of test-driven development before Kent Beck’s rediscovery?
- What is the origin of TDD?
- A History of Test-Driven Development (TDD), as Told in Quotes
- Test Driven Development na przykładzie
- Introduction to Test Driven Development (TDD)
- What is Test Driven Development (TDD)? Example
- Czym jest technika TDD i jak wygląda jej cykl życia?
- TDD Changed My Life
- When to Use Test Driven Development (TDD)
- 5 steps of test-driven development
- What is Test-Driven Development (TDD)?
- Test Driven Development – What it Is, and What it Is Not
- Professional Software Development – Test-driven Development
Zapisz się na mailing i odbierz e-booka
Odbierz darmowy egzemplarz e-booka 106 Pytań Rekrutacyjnych Junior JavaScript Developer i realnie zwiększ swoje szanse na rozmowie rekrutacyjnej! Będziesz też otrzymywać wartościowe treści i powiadomienia o nowych wpisach na skrzynkę e-mail.