Posts Tagged ‘craftsmanship’

Create better defined, shorter and maintainable unit tests with given-when-then sections.

Recently, I’ve been writing rather about more advanced concepts related to automatic testing (mostly related to Spock). However, conducting my testing training I clearly see that very often knowledge of particular tools is not the main problem. Even with Spock it is possible to write bloated and hard-to-maintain test, breaking (or not being aware of) good practices related to writing unit tests. Therefore, I decided to write about more fundamental things to promote them and by the way have a ready to use material to reference when coaching less experienced colleagues.

Introduction

Well written unit tests should meet several requirements and it is a topic for the whole series. In this blog post I would like to present a quite mature concept of dividing an unit test on 3 separate blocks with a strictly defined function (which in turn is a subset of Behavior-driven Development).

given-when-then to the victory

Unit tests are usually focused on testing some specific behavior of a given unit (usually one given class). As opposed to acceptance tests performed via UI, it is cheap (fast) to setup a class to test (a class under test) from scratch in an every test with stubs/mocks as its collaborators. Therefore, performance should not be a problem.

Sample test

To demonstrate the rules I will use a small example. ShipDictionary is a class providing an ability to search space ships based on particular criteria (by a part of a name, a production year, etc.). That dictionary is powered (energized) by different indexes of ships (ships in service, withdrawn from service, in production, etc.). In that one particular test it is tested an ability to search ship by a part of its name.

private static final String ENTERPRISE_D = "USS Enterprise (NCC-1701-D)";

@Test
public void shouldFindOwnShipByName() {
    //given
    ShipDatabase shipDatabase = new ShipDatabase(ownShipIndex, enemyShipIndex);
    given(ownShipIndex.findByName("Enterprise")).willReturn(singletonList(ENTERPRISE_D));
    //when
    List foundShips = shipDatabase.findByName("Enterprise");
    //then
    assertThat(foundShips).contains(ENTERPRISE_D);
}

given-when-then

The good habit which exists in both Test-driven and Behavior-driven Development methodologies is ‘a priori’ knowledge what will be tested (asserted) in a particular test case. It could be done in a more formal way (e.g. scenarios written in Cucumber/Gherkin for acceptance tests) or in a free form (e.g. ad hoc noted points or just an idea of what should be tested next). With that knowledge it should be quite easy to determine three crucial things (being a separated sections) of which the whole test will consist.

given – preparation

In the first section – called given – of a unit test it is required to create a real object instance on which the tested operation will be performed. In focused unit tests there is only one class in which the logic to be tested is placed. In addition, other objects required to perform a test (named collaborators) should be initialized as stubs/mocks and properly stubbed (if needed). All collaborators have to be also injected into the object under test which usually is combined with that object creation (as a constructor injection should be a preferred technique of dependency injection).

//given
ShipDatabase shipDatabase = new ShipDatabase(ownShipIndex, enemyShipIndex);
given(ownShipIndex.findByName("Enterprise")).willReturn(singletonList(ENTERPRISE_D));

when – execution

In the when section an operation to be tested is performed. In our case it is a search request followed by result memorization in a variable for further assertion.

//when
List foundShips = shipDatabase.findByName("Enterprise");

In most cases it is good to have just one operation in that section. More elements may suggest an attempt to test more than one operation which (possibly) could be divided into more tests.

then – assertion

The responsibility of the final section – then – is mostly an assertion of the previously received result. It should be equal to the expected value.

//then
assertThat(foundShips).contains(ENTERPRISE_D);

In addition, it may be necessary to perform a verification of method executions on declared mocks. It should not be a common practice as an assertion on received value in most cases is enough to confirm that code being tested works as expected (according to set boundaries). Nevertheless, especially with testing void methods it is required to verify that a particular method was executed with anticipated arguments.

AAA aka 3A – an alternative syntax

As I’ve already mentioned, BDD is a much wider concept which is especially handy for writing functional/acceptance tests with requirements defined upfront, (often) in a non technical form. An alternative test division syntax (with very similar meaning for the sections) is arrange-act-assert often abbreviated to AAA or 3A. If you don’t use BDD at all and three A letters are easier to remember for you than GWT, it’s perfectly fine to use it to create the same high quality unit tests.

Tuning & optimization

The process of matching used tools and methodologies to ongoing process of skill acquisition (aka the Dreyfus model) has been nicely described in the book Pragmatic Thinking and Learning: Refactor Your Wetware. Of course, in many cases it may be handy to use a simplified variant of a test with a given section moved to a setup/init/before section or initialized inline. The same may apply to when and then sections which could be merged together (into an expect section, especially in parameterized tests). Having some experience and fluency in writing unit tests it is perfectly valid to use shorthand and optimizations (especially testing some non-trivial cases). As long as the whole team understand the convention and is able to remember about basic assumptions regarding writing good unit tests.

Summary

Based on my experience in software development and as a trainer I clearly see that dividing (unit) tests into sections makes them shorter and more readable, especially having less experienced people in the team. It’s simpler to fill 3 sections with concisely defined responsibility than figure out and write everything in the tests at once. In closing, particularly for people reading only the first and the last sections of the article, here are condensed rules to follow:

  • given – an object under test initialization + stubs/mocks creation, stubbing and injection
  • when – an operation to test in a given test
  • then – received result assertion + mocks verification (if needed)

P.S. It is good to have a test template set in your IDE to safe a number of keystrokes required to write every test.
P.S.S. I you found this article useful you can let me know to motivate me to write more about unit test basics in the future.

Picture credits: Tomas Sobek, Openclipart, https://openclipart.org/detail/242959/old-scroll

Self promotion. Would you like to improve your and your team testing skills and knowledge of Spock/JUnit/Mockito/AssertJ quickly and efficiently? I conduct a condensed (unit) testing training which you may find useful.

These posters about SOLID principles were created by me some time ago as a result of reading about alternatives methods of learning and a necessity to apply it in the real world. There are 5 posters about each principle:

  • Single responsibility
  • Open/closed
  • Liskov substitution
  • Interface segregation
  • Dependency inversion

and the one summary page.

How to use it? There are many interesting ways. For example I put the first one on a pinboard in a kitchen when people always look at waiting for water to boil or coffee to brew. I was positively surprised seeing an interest and discussions about subject and created next posters which were hung on top with a 2 weeks delay. After the whole cycle I did a survey on a technical meeting and countable part of attendees declared the posters as a source of knowledge of SOLID principles. I will be happy to hear how did you used it!

SOLID - introduction posters

The text was based on Wikipedia and a very interesting SOLID elaboration – “Pablo’s SOLID Software Development” did by people from LosTechies.com. The illustrative pictures comes also from that e-book in a version mixed by Joey Devilla. Like original materials the slides are available under the terms of Creative Commons Attribution-ShareAlike 3.0 Unported License (which means that you can for example print it and hang in your office).

Let me know if you find it useful. Comments and remarks are also welcome. Thanks!

Gdyby istniała mapa obrazująca położenie osób interesujących się Javą oraz technologiami związanymi z JVM to w minioną sobotę w Warszawie na Dolnym Mokotowie można by było zaobserwować bardzo jasny punkt – uczestników konferencji Confitura 2011. Zgodnie z komunikatem organizatorów w tym roku na konferencji pojawiło się około 800 osób. Cieszy, iż tak duża rzesza ludzi chciała w sobotę przyjść (a czasem nawet przyjechać z daleka), aby przez cały dzień móc dowiedzieć się ciekawych rzeczy i pogłębić swoją wiedzę. Gratulacje i podziękowania dla ludzi zaangażowanych w przygotowanie wydarzenia.

Poniżej zamieszczam slajdy z mojej prezentacji o tworzeniu dobrego kodu. Dziękuję obecnym za liczne przybycie i ponawiam prośbę o przesyłanie uwag i sugestii, abym wiedział, które nad którymi elementami szczególnie powinienem jeszcze popracować (pozytywne mogą być w komentarzach, mocno negatywne proszę na priv ;) ).

Tworzenie dobrego kodu dla niewtajemniczonych Confitura 2011 – slajdy

Największa bezpłatna konferencja społecznościowa dotycząca technologii ze świata Java w Polsce odbędzie się 11 czerwca 2011 w Warszawie. W tym roku po raz pierwszy pod nową nazwą – Confitura (dawniej Javarsovia). Sądząc po pierwszych dniach rejestracji frekwencja ma szansę pobić tę z ubiegłego roku (ponad 650 osób).

Tyle żądnych dowiedzenia się czegoś nowego osób w jednym miejscu na pewno cieszy, ale we mnie budzi również trochę obawy, gdyż jedną z ponad dwudziestu zakwalifikowanych prezentacji będzie moja dotycząca fundamentów Software Craftsmanship i tworzenia dobrego kodu (szczęśliwie planowanych jest kilka ścieżek, więc nikt nie będzie na mnie skazany :) ). To wystąpienie (po prezentacjach w WIT i na Politechnice Warszawskiej) wpisuje się w podjętą przeze mnie w ostatnim czasie próbę propagowania (szczególnie wśród studentów i osób zaczynających przygodę z programowaniem) idei i technik pomagających tworzyć lepsze oprogramowanie w sprawiający więcej przyjemności sposób.

Więcej informacji (w tym możliwość zarejestrowania się) na stronach konferencji.

Confitura Logo

Miałem dzisiaj przyjemność poprowadzić gościnną prezentację o pisaniu dobrego kodu dla niewtajemniczonych na wydziale informatyki Wyższej Szkoły Informatyki Stosowanej i Zarządzania WIT. Mile byłem zaskoczony skuteczną promocją wydarzenia i determinacją studentów, którzy mimo godzin popołudniowych (prawie 18-ta) i nieobowiązkowości wykładu pojawili się w ilości ponad 50-ciu sztuk. Sądząc po wyrazach twarzy większość z nich była żywo zainteresowana tematem.
Niestety w Polsce ruch Software Craftsmanship jest wciąż bardzo mało popularny, mniej nawet niż wiedza o metodykach Agile. Studenci często nie mają w ogóle świadomości, że istnieje alternatywa do metodyk formalnych oraz iż działający kod to jeszcze nie wszystko. Cieszę się, iż mogłem przedstawić kilka aspektów, które pomagają w pisaniu dobrego kodu oraz mam nadzieję, że zachęciłem przynajmniej kilka osób do przeczytania książki “Clean Code” Roberta C. Martina, która w mojej opinii powinna być obowiązkową pozycją na wszystkich kierunkach programistycznych.

Jeżeli byłeś na prezentacji, możesz wyrazić swoją opinię w komentarzu.

Uwaga. Wymienione czynności mogą mieć wiele określeń. Trzeba brać poprawkę, iż podane słownictwo nie jest jedynym słusznym.

Coding Dojo (a.k.a. Code Dojo) jest spotkaniem, na którym grupa ludzi rozwiązuje zadania programistyczne najczęściej w formie Code Kata. Jego celem – oprócz dobrej zabawy – jest wymienianie się praktykami i szlifowanie przydatnych na co dzień umiejętności. Do przeprowadzenia spotkania potrzebne są:
  – sala z miejscami siedzącymi
  – komputer do rozwiązywania zadania (laptop)
  – rzutnik/projektor

Popularnymi rodzajami spotkań są Prepared Kata i Randori Kata (nazwa wywodzi się techniki stosowanej przy ćwiczeniach sztuk walk). Obydwa polegają na implementacji rozwiązania dla postawionego (zazwyczaj prostego) zadania z wykorzystaniem TDD i jednorazowym robieniem małych kroków. Istotne jest, aby każdy na sali orientował się, co w danej chwili jest robione i z czego to wynika. W przypadków pogubienia wskazane jest zadawanie pytań. Wtedy prace implementacyjne powinny być wstrzymane, aż do wyjaśnienia wszelkich wątpliwości.

W przypadku Prepared Kata prowadzący siedzi przed komputerem i wykonuje kolejne kroki: pisze test, implementuje go, dokonuje refaktoringu (w myśl mantry TDD: red, green, refactor). Osoby na sali biorą udział w proponowaniu następnych posunięć. Spotkanie takie jest bardzo przydatne przy wprowadzaniu zasad wśród ludzi, którzy nie mieli wcześniej do czynienia z TDD.

Randori Kata jest bardziej zaawansowaną wersją Prepared Kata. Przy komputerze siedzą jednocześnie dwie osoby, które wymieniają się zadaniami (test – implementacja – refaktoring). Co określony czas (na przykład 5-7 minut) osoba dłużej przebywająca przy komputerze wraca na salę, a w zamian przychodzi ktoś nowy. Jako wariant może istnieć bardziej sztywny podział na role w danej parze (pilot i nawigator). Na zakończenie iteracji pilot wraca na salę, a nawigator przejmuje jego rolę. Osoby nie biorące w danej chwili bezpośredniego udziału w implementacji mogą sugerować rozwiązania i zgłaszać uwagi. Ten typ spotkań jest przeznaczone dla bardziej zaawansowanych grup, aby zapewnić akceptowalny dla wszystkich na sali postęp prac.

Opracowanie zostało przygotowane na podstawie opisu ze strony Coding Dojo, gdzie można znaleźć również szereg zagadnień nadających się do rozwiązania na spotkaniach Coding Dojo.

Tego typu działania są praktykowane w ramach spotkań grupy Warszawa-DP zrzeszającej osoby z Warszawy i okolic zainteresowane wymianą doświadczeń i podnoszeniem swoich umiejętności w zakresie tworzenia dobrego kodu. Na spotkania może przyjść każdy, udział w nich jest bezpłatny. Więcej informacji można uzyskać na liście mailingowej grupy.