“we don’t have time to write tests” == “we don’t have the skills to write tests quickly” – Spock for the rescue

Jakiś czas temu zobaczyłem gdzieś tytułowy cytat i pomyślałem: kurcze gościu ma sporo racji. Często piszemy mało testów bo nie mamy odpowiednich umiejętności żeby robić to szybko a biznes chce tylko nowe funkcjonalności które przynoszą mu kasę. Gościem od cytatu był @AndrzejKrzywda. 😉

W swojej pierwszej pracy przez rok napisałem aż 0 (zero) testów jednostkowych. Nikt nie widział potrzeby ich istnienia. Czym to skutkowało ? Chyba każdy potrafi sobie wyobrazić. Zmiana jednego if’a żeby poprawić buga skutkowała powstaniem 10 następnych. Ale “spoko mamy testerów oni to wykryją…” W sumie to wykrywali, ale więcej czasu poświęcałem na rozmowy z działem QA niż na kodowaniu. Całe szczęście te czasy minęły – zmieniłem pracę i od razu trafiłem do małego projektu gdzie było duże pokrycie testami. Irytacja gdy mała zmiana powodowała “wywalenie się” kilku testów była ogromna. Jako “świeżak” nie widziałem sensu w testowaniu – przecież to tyle czasu na pisanie kodu który nie daje nowej funkcjonalności. Jakby tego było mało w projekcie wszystkie testy były pisane w Groovy z użyciem Spock’a. Jako zagorzały fan Eclipse’a doinstalowałem potrzebne pluginy i zacząłem dodawać kolejne testy.  Wprawiony w Groovy’m trafiłem do kolejnego projektu. A tam czekały na mnie testy z użyciem JUnita…

Zrozumiałem zachwyt kolegów nad Spockiem 🙂

Pierwsza różnica która mnie mocno irytowała ?

Nazewnictwo testów – w Spocku mogłem nazwać test: “Check possibility to add new item to wishlist for not logged user” a w javie ? No pewnie coś takiego można było spotkać: “checkPossibityToAddNewItemToWishlistForNotLoggedUser”, różnica ? zostawię bez komentarza..

Kolejna to oddzielone sekcje dla róznych faz testów – w Spock’u mamy do tego zdefiniowane specjalne bloki(give, when, then, …) a JUnit ? No prawie to samo  – możemy sobie dodać labelki jako komentarze w kodzie, teoretycznie zwiększa nam czytelność testów(…) teoretycznie.

Itd itd.. różnic jest sporo, postaram się opisać niektóre na krótkich przykładach w Groovy. Czy trudno zacząć? Nie! Groovy jest skryptowym językiem z rodziny JVM, oznacza to że pisząc z jego wykorzystaniem możemy mieszać składnie z javą i to będzie działać 🙂

Aby zacząć musimy dodać do projektu poniższe zależności :

oraz plugin odpowiedzialny na zbudowanie kodu napisanego w Groovy:

I to wszystko. Nie musimy niczego instalować w systemie, możemy od razu zacząć pisać testy.

Na początek mały przykład z JUnita:

po uruchomieniu testu w konsoli otrzymamy :

Obiecuję to już ostatnia taka wstawka, teraz skupimy się już tylko na Spocku. A oto odpowiednik powyższego w Groovy:

a w konsoli przyjazny i łatwy do zrozumienia komunikat:

Czytelniej ? Spock pozwala nazwać test w dowolny sposób, co ułatwia opisywanie przypadków testowych.

Przykładowy test zawiera 3 bloki:

  • given – przygotowanie danych
  • when – wywołanie testowanej metody
  • then – weryfikacja

Ale Spock oferuje znacznie więcej  możliwości:

Nie musimy wykorzystywać w naszych testach wszystkich bloków. Użycie jest w pełni uzależnione od tego co chcemy przetestować.

Dodatkowo możemy zaimplementować specjalne metody:

pomagające przygotować środowisko testowe.

Blok where

Jeden z najfajniejszych bloków – daje nam możliwość łatwego przetestowania tej samej metody z różnymi danymi:

Jak to działa? Spock bierze z tabeli zdefinowanej w bloku where po jednym wierszu. Nagłówki tabeli służą jako nazwy zmiennych w teście. Dane są podstawiane w odpowiednim miejscu i test jest uruchamiany N razy. W IDE możemy zobaczyć coś takiego:

Modyfikując nazwę metody i dodając adnotację:

możemy otrzymać poniższy efekt:

Dzięki temu każdy przypadek testowy jest reprezentowany jako osobna pozycja na liście i łatwo możemy zobaczyć ile przypadków i dla jakich danych mamy pokrytych testami oraz ewentualnie łatwo zidentyfikować który z nich przestał przechodzić bo zmieniła się implementacja testowanej metody:

Blok where pozwala nam zaoszczędzić sporo czasu oraz zachować czysty kod.

Jak mockować w Spocku ? Jest dwa podejścia:

A jak mockować komponenty springowe które wstrzykujemy poprzez adnotacje @Autowired i trzymamy w prywatnych polach ? Bardzo łatwo, w teście ustawiamy mocki na testowanej klasie:

“No ale przecież to jest pole prywatne, nie jest widoczne w innych klasach” – no tak ale nie dla Grooviego 😉 dlatego że daje nam on możliwość odwoływania się do pól prywatnych. W jaki sposób ? Generuje nam getter i setter jeśli nie jest zdefiniowany przez programistę. Jest to bardzo wygodne podczas testowania.

Skoro już wiemy jak mockować to przetestujmy coś:

Test zawiera kilka fajnych możliwości Spocka/Grooviego. Przeanalizujmy:

operator >>> zwraca nam kolejną wartość przy każdym wywołaniu mocka, pochodzi ona z tablicy zdefiniowanej w tabeli z danymi.

sprawdza czy wywołanie nie wyrzuca wyjątku, możemy również użyć alternatywnej metody:

dzięki czemu możemy sprawdzić czy rzucany wyjątek jest tym którego oczekujemy.

Sprawdza czy metoda isPerfectSquare została wywołana najwyżej dwukrotnie. Ilość wywołań możemy definiować w dowolny sposób:

 

Spock mimo swej prostoty oferuje nam wiele możliwości, opisać je wszystkie w jednym poście byłoby ciężko, wiec zainteresowanych zachęcam do zadawania pytań, chętnie pomogę zacząć przygodę. Dla tych którzy lubią samodzielnie poznawać nowe narzędzia wrzucam linki:

http://spockframework.org/spock/docs/1.1-rc-3/index.html

http://groovy-lang.org/documentation.html

 

 

 

Leave a Reply

Your email address will not be published. Required fields are marked *