Gwen: BDD-Framework für lesbare und refaktorisierbare Tests in Java

Werkzeuge  –  3 Kommentare

Viele IDEs bieten gute Refactoring-Werkzeuge, jedoch nur wenige sind für Testfälle in der domänenspezifischen Sprache Gherkin ausgestattet. Beim Einsatz des Gwen-Frameworks sind Tests lesbarer Java-Code, wodurch sich die Refactoring-Tools zum Schreiben von Testfällen nutzen lassen.

In der Regel werden Entwickler beim Schreiben von Quellcode durch ihre Entwicklungsumgebung (IDE) unterstützt: Während des Schreibens vervollständigt sie automatisch Methoden, zeigt deren Parameter an und bietet die Möglichkeit, per Tastenkürzel Methoden und Klassen innerhalb eines Projekts umzubenennen.

Um wartbare und langlebige Software zu schreiben, muss der Quellcode verständlich und erweiterbar sein. Wird das Programm Schritt für Schritt ausgebaut, ist der Quellcode bei Bedarf neu zu strukturieren, um verständlich und erweiterbar zu bleiben. Bei derartigen Neustrukturierungen, dem sogenannten Refactoring, werden beispielsweise Variablen umbenannt oder Quellcode in neue Methoden verschoben, um Wiederholungen zu vermeiden. Typsichere Sprachen wie Java vereinfachen den Prozess.

Die gleichen Anforderungen, die für den Quelltext gelten, sind auch für die Testfälle gültig. Sollte einer von ihnen nach einer Codeänderung nicht mehr laufen, muss für Fachabteilung und Entwickler einfach und zuverlässig erkennbar sein, von welchen Annahmen der Testfall ausgeht, was die fachliche Motivation ist und was der Test bezwecken möchte.

Um Sprachbarrieren zwischen Entwicklern und Fachexperten abzubauen, bieten sich Fälle an, die das Verhalten des Systems aus Nutzersicht beschreiben. Ein Vorreiter dieses Behaviour Driven Development (BDD) ist das Cucumber Test-Framework. In der Sprache Gherkin werden darin Features in Szenarien aufgeteilt. Letztere sind, einer Satzschablone gleich, in der immer identischen Struktur Given/When/Then beschrieben:

Feature: Basic Arithmetic

In Order to avoid stupid mistakes
As a cautious person
I use a calculator.

Scenario: simple addition
Given a calculator I just turned on
When I add 4
And I add 5
Then the result is 9

Für jedes Feature der Anwendung werden unterschiedliche Szenarien beschrieben. In jedem sind jeweils der Ausgangszustand aus Sicht eines Nutzers (Given), danach eine oder mehrere durchgeführte Aktionen (When) und schließlich die Nachbedingungen (Then) festgehalten. Diese Beschreibungen lassen sich je nach Entwicklungsvorgehen bereits vor der Umsetzung des Features als Akzeptanzkriterien durch die Fachabteilung formulieren. Die Struktur der Satzschablone stellt dabei sicher, dass Entwickler die Szenarien automatisieren können.

Die Features und Szenarien wertet das Cucumber Framework aus. Für jeden Schritt eines Szenarios müssen Entwickler eine Methode bereitstellen (Step Definitions), der die variablen Anteile des Schritts als Parameter übergeben werden. So können mehrere Szenarien die Methoden verwenden und unterschiedliche Werte übergeben:

public class CucumberSteps {
Calculator c;

@Given("^a calculator I just turned on$")
public void a_calculator_I_just_turned_on()
throws Throwable {
c = new Calculator();
}

@When("^I add (\\d+)$")
public void I_add(long number) throws Throwable {
c.add(number);
}

@Then("^the result is (\\d+)$")
public void the_result_is(long result)
throws Throwable {
assertThat(c.getState()).isEqualTo(result);
}
}

Moderne IDEs wie IntelliJ IDEA zeigen durch Syntax-Highlighting fehlende Methoden an und ermöglichen das Springen vom Testschritt an die entsprechende Codestelle. Über Content Assist zeigen sie beim Schreiben von Code und Tests mögliche Vervollständigungen an, unterscheiden bei den Vorschlägen allerdings nicht zwischen Given, When und Then (Abb. 1). Insgesamt bleiben Content-Assist und Refactoring hinter den Möglichkeiten von Java-Code zurück. Ansonsten zeigt sich erst zur Laufzeit, ob reguläre Ausdrücke, Methoden-Annotationen und Features wie gewünscht zusammenspielen.

Content-Assist für Gherkin in IntelliJ (Abb. 1)