poniedziałek, 25 czerwca 2012

Organizacja Matcherów w testach

Bardzo krótkie wprowadzenie

Do niedawna sądziłem, że pojęcie "matchera" jest wszystkim znane ale przy okazji niedawnej prezentacji o testach mutacyjnych na naszym kochanym łódzkim JUGu okazało się, że część osób ta wiedza ominęła. W skrócie: standardowo w Junit można było napisać coś takiego :

assertEquals(resultDomainObject.getProstawaratosc1,prostawartosc)
assertEquals(resultDomainObject.getProstawaratosc2,prostawartosc)
assertEquals(resultDomainObject.getProstawaratosc3,prostawartosc)
assertEquals(resultDomainObject.getProstawaratosc4,prostawartosc)


Dzięki matcherom możemy przygotować sobie mechanizm do ładnego i zrozumiałego przedstawiania asercji.

assertThatIn(resultDomainObject).thereIsExpectedState().andSomeSomethingElseFulFillsCondition(condition)


Do wyboru z tego co wiem mamy dwie biblioteki:

Organizacja matcherów, która się nie sprawdziła

Początkowo wrzucaliśmy matchery obok testów co okazało się katastrofalnym pomysłem, gdyż nie dość, iż niejednokrotnie pisaliśmy te same matchery po dwa razy to tak naprawdę trudno było kontrolować co już zostało napisane a co jeszcze czeka na wyrzeźbienie.


Wyglądało to tak:
  • paczka1
    • test11
    • test12
    • matcher1
  • paczka2
    • test21
    • test22
    • matcher2


Organizacja matcherów, która może się sprawdzić

Zamiast doklejać matchery do testów dajmy im ich własne pakiety ładnie poukładane według funkcjonalności.
  • testy
    • paczkatestow1
    • paczkatestow2
    • paczkatestow3
  • matchery
    • funkcjonalnosc1
      • konkretnyMatcher1
        konkretnyMatcher2
    • funkcjonalnosc2
      • konkretnyMatcher3
        konkretnyMatcher4
    • Wspolne cegielki
      • cegielkaMatcher1
        cegielkaMatcher2
Na poniższym rysunku widzimy, że dana funkcjonalności ma swój własny i niepowtarzalny matcher, który jest zbudowany na bazie wspólnych, cegiełkowych matcherów :



Czy to dobre rozwiązanie? Czas pokaże.

Konkretny przykład

Poniższy rysunek przedstawia konkretną organizację matcherów w paczkach:



Wykorzystanie matchera wyższego poziomu w teście wygląda tak :

 

 assertThatOnBillingPageRepresentedBy(resultPage).inFirstRow().hasValue("NLD").inCountryCell();



Zaś zastosowanie matchera cegiełkowego do sprawdzania wartości w komórce tabeli wygląda tak: :

 

  assertThatInTableRowHtml(choosenRow).inCellNumber(CELL_NUMBER_OF_CITY).hasValue(expectedValueInCell);



I na końcu jest standard z FESTa :

 

 assertThat(cellText).isEqualTo(value);

poniedziałek, 11 czerwca 2012

W stronę żywej specyfikacji

Czytałem kiedyś bajkę o tym jak to Product Owner tworzy w notatniku wymagania prezentowane przez kilka linijek tekstu, później programiści tworzą z tego testy funkcjonalne i żyli długo oraz szczęśliwie. Bajka nazywała się "Agile coś tam" i miała niewiele obrazków.

Chociaż w głębi duszy wierzę, że wspomniana współpraca, harmonia i trendy słowo : "synergia", są teoretycznie możliwe pomiędzy tzw. "IT" i tzw. "Biznesem", to jednak w praktyce na chwilę obecną ograniczamy się głównie do aktywności ze strony zespołu programistycznego.

Tumbler

Krótko i na temat. Tumbler (tumbler home) pozwala zrobić coś takiego :




(Jeśli ktoś nie wie skąd się wzięły adnotację ---> Behavior Driven Development)

Później generujemy ładny raport :


I nawet to jako tako jest to użyteczne dopóki mamy mało "user stories". Gdy liczba scenariuszy zaczęła zbliżać się do 1500 zauważyliśmy, że już mało komu chce się to czytać.

Tumbler + Maven

W trakcie jednej z prezentacji na GeeCONie, prowadzący ją koleżka wyłożył proste acz idealne rozwiązanie tego problemu

- Jeśli testów jednostkowych nie trzymasz w jednym module to dlaczego masz robić inaczej z testami funkcjonalnymi?

I tak oto rozbijamy sobie projekt, który pełnił rolę worka testowego, na głównego POMa i podmoduły reprezentujące konkretne ficzery:



Teraz zostaje nam już tylko odpalić mvn clean test (czasem trzeba dać install na commonie) i w każdym pod module pojawi się ładny mini raport.

I już tylko pozostaje nam poskładać to wszystko do kupy...

+ Groovy

Zakreślony na czerwono pliczek odpalamy na sam koniec. Znajdzie on wszystkie raporty i sklei w całość:



A jak klikniemy w w nagłówek sekcji to zobaczymy raport szczegółowy z domeny danego ficzera:



I dalej schodzimy do poziomu pojedynczych user story.

Do szczęścia pozostaje już tylko dopracowanie tekstów w Given, When, Then tak aby ci biedni ludzie zza miedzy wiedzieli o co w tym wszystkim chodzi