Framework JUnit 5 ma szerokie zastosowanie w testach jednostkowych, natomiast w powiązaniu z biblioteką Cucumber jego możliwości wchodzą na wyższy poziom - testów funkcjonalnych. W przeszłości integracja obu bibliotek była dość uciążliwa, jednak z pomocą przychodzi nowe rozwiązanie cucumber-junit-platform-engine, które znacznie upraszcza to połączenie. Poniższy post przedstawia, jak to zaimplementować przy użyciu Gradle.

Cucumber

Język Gherkin jest oparty na plikach z rozszerzeniem .feature, w którym opisujemy scenariusze testowe. Powinny zawierać te same słowa kluczowe, których używa zespół do omówienia funkcji.

Feature: Guess the word

  Scenario: Maker starts a game
    Given the game is setup
    When the Maker starts a game
    Then the Maker waits for a Breaker to join

Każdy scenariusz opisuje serię kroków, które rozpoczynają się od słów kluczowych takich jak Given, When i Then. Aby zdefiniować logikę stojącą za tymi krokami, potrzebujemy bardzo niewiele ‘glue code’:

package your.own.steps;

import io.cucumber.java.en.When;
import io.cucumber.java.en.Then;

public class YourSteps {

	@Given("the game is setup")
	public void setup() {
		// execute step
	}

	@When("the Maker starts a game")
	public void someStep() {
		// execute step
	}

	@Then("the Maker waits for a Breaker to join")
	public void otherStep() {
		// execute other step
	}

}

Do uruchomienia scenariuszy testowych niezbędne są zarówno pliki .feature, jak i wspomniany ‘glue code’.

JUnit 5

Jedną z największych zalet JUnit 5 w porównaniu z jego wcześniejszą wersją jest jego rozszerzalność. Twórcy Cucumber’a wykorzystali wspomnianą cechę do stworzenia platform-engine, który przekazuje pliki .feature i ‘glue code’ oraz wykonanie testu do biblioteki JUnit. Wszystko czego potrzebuje programista to dodanie zależności i dodatkowa klasa z adnotacją @Cucumber.

package your.own;

import io.cucumber.junit.platform.engine.Cucumber;

@Cucumber
public class RunCucumberTest {
}

Gradle

Używamy Gradle, aby zadeklarować wszystkie wymagane zależności i skonfigurować w jaki sposób mamy uruchamiać nasze testy. Poniższy fragment kodu pokazuje minimalny przykład napisany w Kotlinie, za pomocą którego możemy uruchomić Cucumber’owe scenariusze.

plugins {
  java
}

dependencies {
  testImplementation("org.junit.jupiter:junit-jupiter-api:latest.release") {
	because("we want to use JUnit 5")
  }
  testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:latest.release") {
	because("Cucumber relies on jupiter-engine to resolve tests")
  }
  testImplementation("io.cucumber:cucumber-java:latest.release") {
	because("we want to use Cucumber JVM")
  }
  testImplementation("io.cucumber:cucumber-junit-platform-engine:latest.release") {
	because("we want to use Cucumber with JUnit 5")
  }
  testImplementation("io.cucumber:cucumber-picocontainer:latest.release") {
	because("we want to use dependency injection in our Cucumber tests")
  }
}

tasks {
    test {
        systemProperties(System.getProperties().toMap() as Map<String, Any>)
        systemProperty("cucumber.execution.parallel.enabled", System.getProperty("test.parallel"))
        systemProperty("cucumber.filter.tags", "not @ignore")
        useJUnitPlatform {
            excludeTags("disabled")
        }
    }
}

Kiedy powyższy krok zostanie zaimplementowany, wystarczy wywołać polecenie gradle test, aby przetestować scenariusze. Zaprezentowany przykład kodu pokazuje, jak przekazać parametry do testu, aby np. umożliwić równoległe wykonanie testów lub włączyć/wyłączyć pewne scenariusze.

W repozytorium https://github.com/cronn-de/cucumber-junit5-example znajdziecie kompletny projekt który pozwoli Wam szybko wystartować z integracją JUnit5 i Cucumber.