Praxiserfahrungen mit Behaviour-Driven Development in einem Softwarekonzern

Seite 2: Behaviour-Driven Development konkret

Inhaltsverzeichnis

Beim Behaviour-Driven Development (BDD) dient der Test zugleich als Dokumentation und Planung der Anforderungen. Eine neue Funktion wird nicht mittels Ablaufdiagrammen oder Ähnlichem geplant, sondern schriftlich in der Syntax der verhaltensgetriebenen Entwicklung festgehalten. Hierfür ist es notwendig, dass Kunden bei der Planung vor Ort ist. In einem typischen Entwicklungsteam übernehmen die Product Owner die Rolle der Kunden. Durch die dauerhafte Verfügbarkeit der Kunden lassen sich Fragen und Probleme jederzeit klären und der Arbeitsablauf anpassen.

Um die beschriebenen Techniken umzusetzen, sind verschiedene Werkzeuge hilfreich. Einen Test im Behaviour-Driven Development kann man mit dem Framework Cucumber und der Beschreibungssprache Gherkin definieren. Hierbei folgt ein BDD-Test immer einem festen Schema von Schlüsselwörtern. Beginnend mit "Gegeben sei" oder "Angenommen" wird zuerst der Kontext definiert, in dem der Test stattfindet. Anschließend werden Aktionen mit dem Schlüsselwort "Wenn" eingeleitet und das erwartete Ergebnis mit dem Schlüsselwort "Dann" geprüft (s. das folgende Listing).

# language: de

Funktionalität: Addition
  Mein Taschenrechner soll die Addition beherrschen

  Szenario: Regular numbers
    Angenommen, ich habe die Zahl 10 in den Taschenrechner eingegeben
    Und ich habe die Taste "+" gedrückt
    Und ich habe die Zahl 5 in den Taschenrechner eingegeben
    Wenn ich auf die Taste "=" drücke
    Dann wird als Resultat 15 auf dem Bildschirm ausgegeben

Es besteht die Möglichkeit, mehrere Schritte desselben Typs zu nutzen. Das Verknüpfen dieser Schritte geschieht durch das Schlüsselwort "Und". Ein Feature-File bündelt thematisch zusammengehörige einzelne Tests. Es enthält einen Titel und eine kurze Beschreibung der Intention. Die Definition der Schritte kann in verschiedenen Sprachen erfolgen. Englisch gilt als Standardsprache. Soll eine andere Sprache genutzt werden, ist diese in der ersten Zeile anzugeben. Nach dem Schreiben des Feature-Files werden die Schritte programmatisch umgesetzt. Die Umsetzung im Code erfolgt aus einer Kombination von Annotationen und einer speziell für Cucumber angepassten Art von Regex. Eine Schritt-für-Schritt-Implementierung kann auch Variablen enthalten, die automatisch aus der Textdefinition extrahiert werden (s. das folgende Beispiel).

import io.cucumber.java.de.Angenommen;

public class Addition {

    @Angenommen("Ich habe die Zahl {int} in den Taschenrechner eingegeben")
    public void ichHabeDieZahlInDenTaschenrechnerEingeben(int zahl) {

    }
}

Mögliche Programmiersprachen für die Umsetzung sind Java, JavaScript, C++ sowie alle auf der Java Virtual Machine (JVM) basierenden Sprachen. Die Verknüpfung zwischen Schritt-für-Schritt-Implementierung und Feature-File findet automatisch durch Cucumber statt. Hierfür ist nur eine einmalige Konfiguration mittels der so genannten CucumberOptions notwendig. Viele Entwicklungsumgebungen bieten mittlerweile sogar mit entsprechenden Plug-ins das Debuggen eines Feature-Files an.

Für die Zusammenarbeit zwischen den verschiedenen Paaren ist Git mit entsprechenden Review-Guidelines und verbindlichen Code-Guidelines notwendig. Auch muss man eine Form des Pairings finden. Hierfür gibt es verschiedene Möglichkeiten. Grundlegend kann man das Zusammenarbeiten virtuell oder vor Ort gestalten. Vor Ort hat den Vorteil, dass der direkte Austausch einfacher und die Konzentration höher ist. Für das virtuelle Pairing ist ein geeignetes Tool notwendig. Das Teilen des Bildschirms mittels Teams, Skype oder Slack ist oft unscharf und zeitverzögert. Das erschwert die Zusammenarbeit erheblich. Aus diesem Grund sollten Teams den Einsatz spezieller Pairing-Tools wie "Code With Me" für IntelliJ-Produkte oder das "Live Sharing Extension Pack" für VS Code evaluieren. Mit diesen Plug-ins wird nicht der Screen als Ganzes geteilt. Stattdessen öffnen beide Paare die jeweilige Entwicklungsumgebung. Die gerade programmierende Person ist Host der Session. Die andere nimmt als Beobachter teil und sieht alle ausgeführten Aktionen.