Testowanie BDD w Cucumber-jvm

Testować trzeba.

Wiem, nie zawsze jest czas, nie zawsze są chęci, zawsze jest coś ważniejszego. Ale im wcześniej zrozumiemy, że bez jakichkolwiek testów, nie jesteśmy w stanie napisać czegoś większego, tym szybciej nabierzemy dobrych praktyk, i okaże się, że nie są one aż takim wrzodem na … tyłku.

Jak testować? Pewnie każdy zna o używa JUnit. Jak nie wiesz co to, idź poczytać do wujka Google, potem wróć tutaj 😉

Testy jednostkowe to jedno, ale czy dałoby się je jakoś … ubiznesowić? Czy dałoby się testować tak, żeby ludzie z managementu, analitycy wiedzieli co jest zrobione, co działa, co ma błędy? Okazuje się, że takim rozwiązaniem jest BDD czyli Behavior Driven Developement.

BDD jest można powiedzieć rozszerzeniem TDD (Test Driven Development), który opiera się na testowaniu gotowych zachowań (funkcjonalności) poprzez implementację tzw. User Stories. User Stories to są sformalizowane historyjki dotyczące funkcjonalności. Historyjki te są zrozumiałe dla innych nie-developerów, mogą stanowić nawet podstawę testów akceptacyjnych dla klienta. Mamy więc rozwiązany problem pytania – czy dana funkcjonalność działa ? Jeśli są napisane dobre historyjki, jeśli testy są napisane, to możemy prawie z pewnością opowiedzieć – TAK.

Jak się więc zabrać za BDD?
Na początek historyjki… dobry i w miarę czytelny opis czym jest user story i jak to pisać jest tutaj: http://dannorth.net/whats-in-a-story/

Napiszmy więc jakiś scenariusz…

Widać od razu co chcemy przetestować. Wystarczy to w jakiś sposób zaimplementować…
Z pomocą przychodzą różne nardzędzia. Tutaj skupię się na Cucumber-jvm

Instalacja tego cuda polega na dodaniu odpowiedniego dependency dla maven:

Miałem mały problem aby wszystko zadziałało musiałem jeszcze mvn powiedzieć, żeby używał javy 8 😉 Wpisz do <properties></properties>

Gdy maven sobie przemyśli sprawę i ściągnie wszystkie zależności, musimy jeszcze tylko skonfigurować nasze środowisko…

Kilka uwag do tego co napisałem – Adnotacja @CucumberOptions podaje dodatkowe opcje do Cucumbera. @RunWith mówi, że będziemy go używać. Strasznie trudne.
Na moment zatrzymam się przy opcjach. Jest ich trochę.
Domyślnie cucumber szuka feature files (o nich za moment) w katalogu resources (np w src/main/resources lub src/test/resources). Dla mnie to nie jest fajny katalog, więc zamieniam go sobie na inny.
Dodatkowo możemy upiększyć raporty generowane przez cucumber’a – plugin = pretty – więcej kolorków na konsoli 😉 html:out – zgadnijcie – tak, wygenrowany zostanie raport z testów do htmla, który możemy podrzucić analitykowi, managerowi, komu chcemy 🙂 Można to wszystko poprzez jakiś mechanizm CI podrzucić też tam. Jak to lubi, jak kto potrzebuje.

Dobra.. Teraz jak dodawać scenariusze ?

tworzymy feature file – plik z rozszerzeniem .feature i opisami historyjek… ładujemy go tam gdzie wskazaliśmy w cucumberOptions albo do katalogu resources – jak kto woli

Napisałem sobie prosty feature….

Krótko o tym co tam jest…

Feature: OPIS co będzie w tym pliku feature

Scenario: Nazwa scenariusza.. co ten scenariusz robi..

Given: Warunki początkowe
When: akcja
Then: co ma być wynikiem akcji

Dodatkowo możemy używać słów AND oraz BUT aby nieco rozszerzyć nasze historyjki o dodatkowe założenia, wyniki itp.

Teraz będzie fajnie.

Popatrzcie na pierwszy scenariusz – w WHEN mamy podaną liczbę. Będzie ona przekazana automatycznie do testów! Tak samo jakbyśmy użyli cudzysłowów „wartość”, będzie ona też przekazana do testów 🙂 Listę przekazujemy tak jak poniżej w kolejnym teście. Daje nam to bardzo duże możliwości automatyzowania, konfigurowania testów. Możemy sprawdzić, czy logika zachowa się tak samo dla różnych wartości, dla różnych ilości itp…

No dobra, mamy historyjke… jak je zaimplementować? Banalnie 😀 Cucumber sam na zrobi odpowiednie metody… wystarczy, że wpiszemy:

i po chwili dostaniemy coś podobnego do tego:

Ha! to są nasze kroki, zamienione na kod Javy! No to jesteśmy prawie w domu… Wystarczy stworzyć klasę i wkleić te kroki do niej, zrobić odpowiednie importy… mi wyszło coś takiego…

Teraz po ponownym odpaleniu testów mamy wyniki…

Exception PendingException jak widać powoduje nie wykonanie testów 😉

To teraz musimy je zaimplementować…

Pełna implementacja przykładu i klasy jest na github jak zawsze:  https://github.com/najavie/cucumber-jvm-example1

 

Same testy wyglądają tak:

 

Nic strasznego, kilka assertów itp…

Ważne – musiałem utworzyć kilka obiektów pomocnicznych do tych testów ( te private static … na początku), ponieważ muszę przekazać jakoś stan pomiędzy krokami.

Jak spojrzycie, to domyślne metody wygenerowane przez Cucumbera miały w parametrach cuda pod nazwą DataTable… Można ich używać, ale nie zawsze są wygodne, trzeba się odwoływać do pól, nazw, kupa pisania i mało wygodne. Jednak można użyć własnych obiektów, o ile ich pola będą się zgadzały z definicją podaną w feature file. A to już bardzo upraszcza sprawę 🙂

I teraz piękno tych testów… Metody historyjek są reusable 🙂 Możemy je użyć wielokrotnie do innych testów (przydaje się to np w metodach CRUD dla aplikacji www – piszemy jeden test sprawdzający dany obiekt i używamy go do dodwania, aktualizacji listowania…) .. DRY (Don’t repeat yourself) w pięknej postaci. Dodatkowo, możemy testować te same historyjki w wykorzystaniem różnych danych wejściowych i sprawdzać jak się zachowa aplikacja, Co będzie jeśli podamy pustą listę? Nie musimy pisać osobnej metody, wystarczy przesłać pustą listę parametrów… zły login/password ? też można to sprawdzić od razu 🙂

Dodajmy taką historyjkę:

Coś ciekawego – jak odpalimy mvn test, dostaniemy do implementacji tylko jedną metodę (When I add new user…). Cała reszta jest już zaimplementowana!

Więc dodanie kolejnego scenariusza = dodanie jednej metody. Ale fajnie…

Napiszmy ją…

i po odpaleniu mvn test… wszystko się na zielono świeci 🙂 Jest super…

Oczywiście testy, które napisałem są banalne, ale chodziło mi tylko o pokazanie tego, że pisanie testów w BDD nie są wcale trudne, w wielu przypadkach są prostsze od pisania zwykłych testów jednostkowych, a poprzez odpowiednio napisane user stories możemy uprościć sobie życie, pokazać analitykom, managerom, że mają od razu napisane testy akceptacyjne… Mniej roboty, deadline bezpieczny, klient zadowolony, aplikacja przetestowana… i można spać spokojnie 😀