Given When Then w testach

Co to jest given-when-then?

given-when-then to popularny styl do specyfikacji zachowania aplikacji.  W przypadku jego stosowania test podzielony jest na trzy sekcje.

  • Given tworzy sekcję w której tworzymy założenia początkowe. Ustawiamy stan systemu (zwany również stanem świata) na potrzebny do testów.
  • When w tej sekcji wykonujemy akcję którą chcemy testować.
  • Then wykonujemy sprawdzenia czy aplikacja zachowała się zgodnie z oczekiwaniami. Najczęściej poprzez wykorzystanie asercji lub interakcji z mockami

Nie zawsze potrzebne są wszystkie sekcje w ramach jednego testu. Na przykład gdy ustawiamy pewne wartości w ramach metody setUp(). Ogólnie przyjęło się, że stosowanie takiego podziału jest dobrą praktyką, ponieważ test staje się przez nią jasno podzielony na etapy i dokładnie wiemy czego spodziewać się po każdym z nich. Dla oznaczenia podziału najczęściej wykorzystuje się komentarze w kodzie. Przykładowy test w takim wypadku może wyglądać następująco:

@Test
public void shouldNeverServeCoffeeIfNoRemaining() {
	// given
	Cafe cafe = new Cafe();
	cafe.setCoffeesRemaining(1);

	// when 
	cafe.serveCoffee();

	// then
	assertFalse(cafe.canServeCoffee());
}

 

Używanie etykiet w JUnitach

Do dzielenia kodu można by również pokusić się o użycie etykiet (ang. label) w celu podziału sekcji. Kod wyglądałby wtedy jak poniżej.

Cafe cafe = new Cafe();

@Test
public void shouldNeverServeCoffeeIfNoRemaining() {
	Given:
	cafe.setCoffeesRemaining(1);

	When:
	cafe.serveCoffee();

	Then:
	assertFalse(cafe.canServeCoffee());
}

Jest to nietypowe wykorzystanie etykiet w ten sposób. Najczęściej są one wykorzystywane do wyjścia z zagnieżdżonych pętli. Oczywiście nie istnieje żaden dobry powód, żeby ich w ogóle używać. Zostały uznane jako zła praktyka programowania, najczęściej znacznie zmniejszają czytelność kodu. Z semantycznego punktu widzenia nie ma różnicy między kodem z oraz bez etykiet.  

Używanie etykiet z Lambda Behave

Większość deweloperów korzysta z biblioteki JUnit. Należy jednak być świadomym fakty, że istnieją do niej alternatywy. Jedną z nowszych takich alternatyw jest Lambda Behave. Jest zaprojektowania do bycia nowoczesnym frameworkiem testowym i behawioralnym dla Java 8. Ułatwia pisanie bardziej czytelnych testów. W przeciwieństwie do JUnitów nie konieczności definiowania nazwy testu w formie nazwy metody. Testy w pisane w tym stylu są łatwiejsze do czytania. Przykładowy test wykorzystujący etykiety do zdefiniowania sekcji given-when-then.

describe("a cafe", it -> {
 
      Cafe cafe = new Cafe();
 
      it.should("never serve coffee it doesn't have", expect -> {
          Given:
          cafe.setCoffeesRemaining(1);
 
          When:
          cafe.serveCoffee();
 
          Then:
          expect.that(cafe.canServeCoffee()).is(false);
      });
 
  });

 

Ograniczenia i alternatywy

Największą dolegliwością powyższych przykładów jest to, że nie można, z jakiegoś powodu, zapisać polecenia utworzenia zmiennej po etykiecie. Znaczy to tyle, że jeśli po Given: potrzebujemy dostępu do zmiennej, to będziemy musieli ją stworzyć wcześniej lub tworzyć ją w osobnej metodzie. Z drugiej strony nie jest to aż tak problematyczne i może dodatkowo poprawić czytelność kodu. Jako alternatywy, możliwe, że bardziej popularnej, można użyć podejścia z komentarzami. Wybór między tymi dwoma podejściami jest na poziomie stylistycznym. W obydwóch podejściach piszemy dodatkowy, wyjaśniający kod. W przeciwieństwie do wbudowywania takiej funkcjonalności w framework testowy, tak jak jest w przypadku np. Cucumber lub JBehave. Wybór najczęściej będzie to zależał od ustaleń z innymi członkami zespołu. Należy podjąć decyzję raz i konsekwentnie się jej trzymać. Część ludzi używa alternatywnych wzorców do given-when-then, które są podobne, ale mają na przykład więcej etapów, tak jak podejście four phase test albo korzystające z innych nazw, np: Arrange, Act, Assert. Możliwe jest użycie podejścia z etykietami również w tych konwencjach.  

Wnioski

Kod źródłowy artykułu można znaleźć na GitHubie, dla zainteresowanych i chcących pobawić się tym w ramach własnego IDE. Nie ma tam zbyt dużo kodu, ponieważ są to tylko proste przykłady. Można się jednak przekonać, że nie stoi za tym żadna magia. Pokazano jak można użyć etykiet do zwiększenia przejrzystości swojego kodu. Możliwe, że ktoś uzna tę technikę za pomocną i użyteczną. Niezależnie od wybranego sposobu oznaczania sekcji testów, warto korzystać z tej konwencji. Zdecydowanie można w ten sposób poprawić czytelność testów. Jakie są Wasze opinie na ten temat?   Autor: Richard Warburton Źródło: http://insightfullogic.com/blog/2015/jan/19/given-when-then-java/

Dyskusja i komentarze

Masz pytania do tego wpisu? Może chcesz się podzieliś spostrzeżeniami? Zapraszamy dyskusji na naszej grupe na Facebooku.