BDD przy użyciu JGiven, czyli jak ułatwić sobie pracę

BDD czyli Behavior-Driven-Development jest metodą programowania, w której klienci biznesowi, programiści i testerzy opisują zachowanie aplikacji przy pomocy scenariuszy. Scenariusze pisane są przy użyciu uzgodnionej notacji i języka, tak aby były zrozumiałe dla wszystkich stron. Co jeszcze warto o niej wiedzieć?
Biblioteka JGiven w służbie BBD
Dzisiaj przedstawię bibliotekę JGiven wspomagającą proces BBD. Aktualnie dla języka Java istnieją już rozwiązania, takie jak JBehave czy Cucumber. Co może nam więc zaproponować biblioteka JGiven? Warto wiedzieć, że:
- scenariusze pisane są w języku Java, zamiast tak, jak w przypadku pozostałych bibliotek, używając zwykłego tekstu,
- scenariusze wykonywane są przez JUnit lub TestNG,
- scenariusze dzielą się na etapy, a stan ich wykonania jest przekazywany między nimi przy użyciu wstrzykiwania,
- JGiven generuje raporty wykonania scenariuszy.
Przykład użycia JGiven
Tak prezentuje się test, który może zostać przygotowany przez klienta.
@Test
public void we_can_buy_a_ticket_from_wroclaw_to_berlin_for_ten_euros(){
given().an_origin_city("Wroclaw")
.and().destination_city("Berlin");
when().we_press_button()
.and().insert_money(10.0f);
then().the_resulting_ticket_should_be_valid_for_travel_from_wroclaw_to_berlin();
}
Widać tutaj podział na 3 etapy: Given, When i Then. Pozwala to na rozdzielenie logiki testu do osobnych klas.
Klasa testowa rozszerza klasę ScenarioTest i przekazuje typy klas dla poszczególnych etapów:
public class TicketsMachineScenarioTest extends ScenarioTest<GivenCities, WhenBuy, ThenTicket>
Każdy z etapów jest klasą rozszerzającą Stage. Dane między etapami przekazujemy korzystając z adnotacji @SenarioState, @ProvidedScenarioState, @ExpectedScenarioState. Każda z tych adnotacji działa tak samo, ich różne nazwy zostały stworzone tylko po to, aby lepiej odwzorowywać kontekst użycia.
Tak wyglądają klasy etapów dla powyższego testu:
Given
public class GivenCities extends Stage<GivenCities> {
@ProvidedScenarioState
String originCity;
@ProvidedScenarioState
String destinationCity;
public GivenCities an_origin_city(String city) {
originCity = city;
return this;
}
public GivenCities destination_city(String city) {
destinationCity = city;
return this;
}
}
When
public class WhenBuy extends Stage<WhenBuy> {
TicketsMachine ticketsMachine;
@ExpectedScenarioState
String originCity;
@ExpectedScenarioState
String destinationCity;
@ProvidedScenarioState
Ticket ticket;
public WhenBuy(){
ticketsMachine = new TicketsMachine();
}
public WhenBuy we_press_button() {
assertNotNull( ticketsMachine );
ticketsMachine.selectCities(originCity, destinationCity);
return this;
}
public WhenBuy insert_money(float money) {
assertNotNull( ticketsMachine );
ticket = ticketsMachine.buyTicket(money);
return this;
}
}
Then
public class ThenTicket extends Stage<ThenTicket> {
@ExpectedScenarioState
Ticket ticket;
public void the_resulting_ticket_should_be_valid_for_travel_from_wroclaw_to_berlin() {
assertNotNull(ticket);
assertTrue(ticket.isOriginCity("Wroclaw"));
assertTrue(ticket.isDestinationCity("Berlin"));
}
}
Metody w etapach Given i When powinny zwracać referencję do danych siebie, dzięki temu, możemy używać podstawowych metod z klasy Stage i łączyć nasze wywołania przy użyciu and(), with(), but().
Raport końcowy
Raport testowy wygenerowany dla tego przykładu wygląda następująco:
We can buy a ticket from wroclaw to berlin for ten euros
Given an origin city Wroclaw
And destination city Berlin
When we press button
And insert money 10.0
Then the resulting ticket should be valid for travel from wroclaw to Berlin.
Biblioteka JGiven jest bardzo ciekawym narzędziem wspomagającym proces tworzenia oprogramowania. Jest ona dość prosta w użyciu, a zarazem posiada wiele mechanizmów ułatwiających pracę. Pozwala na łatwe rozdzielenie etapów testów oraz tworzenie scenariuszy testowych w języku Java, co zmniejsza ilość pracy, jaką musi wykonać programista. Osobiście zachęcam do jej sprawdzenia. Więcej informacji znajdziecie na stronie http://jgiven.org/