Behavior Driven Development

In Projekten kommt es immer wieder vor, daß Kunden und Business Analysten bei der Präsentation der Ergebnisse einer Softwareentwicklung ihre Anforderungen nicht umgesetzt sehen. Gründe dafür können z.B. unspezifische Anforderungen, fehlende Beispielfälle und Mißverständnisse bei der Interpretation der Anforderungen sein. Softwareentwickler leiten aus der sprachlichen Spezifikation Testfälle in Programmcode ab, die von technikfernen Projektbeteiligten nur schwer verstanden und geprüft werden können. Wie kann es ermöglicht werden, diese automatischen Tests lesbarer zu gestalten, so daß sie durch Business Analysten und Kunden geschrieben und abgenommen werden können? Bei der Suche nach Lösungen bin ich auf "Behavior Driven Development" gestoßen.

Behavior Driven Development (BDD) ist eine Technik der Agilen Softwareentwicklung und bindet Business Analysten und Kunden enger in die Softwareentwicklung ein. Ähnlich wie beim Test Driven Development (TDD), wird zunächst das erwartete Verhalten in einer automatisiert ausführbaren Weise beschrieben und dann der eigentliche Anwendungscode sukzessive verändert, um das gewünschte Verhalten zu erreichen.

Beim TDD wird dies durch direkte Implementierung eines Tests in der jeweiligen Programmiersprache umgesetzt, d.h. es wird direkt Programmcode in Form eines Test geschrieben.

BDD will eine engere Einbeziehung der Business Analysten und Kunden erzielen. Das erwartete Verhalten wird textuell in normaler menschlicher Sprache beschrieben, wobei bestimmte Schlüsselwörter verwendet werden müssen, z.B. "Angenommen ...", "Um ...", "Wenn ...", "Dann ...". Für die präzisere Darstellung des Verhaltens werden oft Beispieldaten angegeben. Um diese textuelle Beschreibung als Testfall laufen lassen zu können, wird von den Entwicklern ein Bridge-Objekt gebaut, das die Brücke zum Anwendungscode herstellt. Ab dann können die Tests wiederholt automatisiert ausgeführt werden. Ähnlich wie beim TDD wird der Anwendungscode von den Entwicklern dann schrittweise verändert, um die Testfälle zu erfüllen. Business-Analysten und Kunden können anhand des Testprotokolls jederzeit leicht den Status der Anwendungsentwicklung nachvollziehen.

Es existieren mehrere Frameworks in verschiedenen Programmiersprachen für die Umsetzung von BDD, z.B. JBehave und Jnario für Java, Cucumber für Ruby. Um die BDD-Vorgehensweise konkreter kennenzulernen, schauen wir uns im Weiteren ein Beispiel an - der Kürze und Einfachheit wegen mit Cucumber in Ruby on Rails:

Beispiel

Bankkunden können Finanzierungsanträge stellen, wobei der Finanzierungsbetrag, die Laufzeit sowie der von der Bank veranschlagte Zinssatz angegeben werden müssen. Bei einer jährlichen Rückzahlung eines konstanten Betrags (Annuität) soll nun die Anwendung erweitert werden, so daß dem Bankkunden eine Übersicht über die Restschuld pro Jahr gegeben werden kann.

Beispieldaten

Finanzierungsbetrag: 25.000 EUR
Laufzeit: 5 Jahre
Zinssatz: 7,5%

Daraus ergibt sich bei einer jährlichen Zahlung (Annuität) von 6.179,12 EUR folgender Verlauf der Restschuld am Ende des jeweiligen Jahres:

 


Die Anwendung enthält bereits ein Modell, das zu Finanzierungsanfragen bisher nur die Eingabedaten verwaltet:

Das erwartete Verhalten wird nun als Feature spezifiziert, wobei die Beschreibungssprache "Gherkin" verwendet wird, die in 40 Sprachen bestimmte Schlüsselwörter beinhaltet. In der Spezifikation können tabellarische Beispieldaten angegeben werden:

Dieser Szenariogrundriss mit den gegebenen Beispielen ist nun unser Test! Dieser Test kann tatsächlich ausgeführt werden:

ie funktioniert diese Ausführung der Spezifikation unseres Features?

Jede Zeile des Szenariogrundriss muss mit einem Gherkin-Schlüsselwort beginnen und wird einzeln ausgewertet. Cucumber sucht dann in Dateien der "Step Definitions" nach regulären Ausdrücken, die auf den verwendeten Zeilentext passen.

Wenn wir unseren Test ausführen, wird jede Zeile der Beispiele durchlaufen und getestet: Im Text des Szenariogrundrisses werden die Platzhalter durch die jeweiligen Testdaten ersetzt. Mit diesen Zeilen werden nun die regulären Ausdrücke der Step Definitions aufgerufen. Der erste Durchlauf verwendet also:

Als Erstes implementieren wir nun also die passenden Steps - diese können auch von mehreren Features benutzt werden, solange die Formulierung in den jeweiligen Szenariogrundrissen identisch ist und somit derselbe reguläre Ausdruck greift.

Unsere Implementierung der Steps soll jedesmal ein neues FinanzierungsAntrag-Objekt erstellen, den Betrag, Zeitraum und Zinssatz zuweisen. Dann wird die Methode "restschuld" auf dem Objekt ausgeführt, die aber aktuell noch nicht existiert. Das erwartete Ergebnis der Beispieldaten soll schließlich mit dem erechneten Ergebnis verglichen werden:


Führen wir unseren Test jetzt erneut durch:

an sieht, daß die Zeilen des Szenariogrundrisses richtig erkannt und den Steps zugeordnet werden. Die Beispieldaten werden richtig gesetzt, aber leider führt die Verwendung der Jahresdaten zu einem Fehler, da die Methode "restschuld" noch nicht existiert. Der erwartete Restschuld-Wert konnte dann nicht verglichen werden, da bereits vorher ein Fehler auftrat.

Jetzt haben wir also unser Feature spezifiziert und die Infrastruktur geschaffen, um es ausführen zu können. Jetzt sollten wir (ganz wie in TDD) unseren Test sukzessive zur korrekten Ausführung bringen. Dafür wird im Modell FinanzierungsAnfrage die Methode "restschuld" implementiert, zusammen mit einigen privaten Hilfsmethoden:

Unser Test zeigt nun, ob unsere Implementierung das Feature korrekt umsetzt:


Zusammenfassend zeichnet sich BDD aus durch:

  • Stärkere Einbeziehung von Business Analysten und Kunden in den Softwareentwicklungsprozeß
  • Textuelle Beschreibung der Anforderungen an die Anwendung und Nutzung von Fallbeispielen
  • Automatisierte Durchführung der Anforderungen als Testfälle durch Bridge-Objekte zur Anwendung
  • Anpassung der Anwendung zur Erfüllung der Testfälle, ähnlich wie in TDD
  • Möglichkeit der Abnahme der Softwareentwicklung durch den Kunden anhand der Testprotokolle

So gut BDD auch klingen mag, gibt es auch Kritker: Es wird einiger Aufwand betrieben, um Anforderungen in (fast) menschlicher Sprache als Test automatisch ablaufen zu lassen; Software-Entwickler müssen den notwendigen Bridge-Code schreiben. Dieser Code muss gepflegt werden, die Wiederverwendbarkeit muss gezielt gefördert werden - hier zeigt sich dann die enge Kopplung zwischen der Formulierung der Anforderungen und dem Bridge-Code, denn leichte Abweichungen der Formulierung ziehen Änderungen des Codes nach sich und umgekehrt setzt eine Wiederverwendung von Bridges die Verwendung gleicher Textbausteine voraus. Mißverständnisse in der Interpretation von Anforderungen kann es auch bei der Entwicklung von Bridge-Objekten geben, aber die Kunden und Business Analysten sind enger in den Entwicklungsprozeß eingebunden und sind durch die geforderte Schreibweise von Features dazu angehalten, ihre Anforderungen detailierter zu durchdenken und zu spezifizieren. Selbst wenn Kunden und Business Analysten ihre Anforderungen nicht selbst in der geforderten Art und Weise beschreiben, sondern Architekten oder Entwickler diese Aufgabe übernehmen, so können diese Tests dennoch reviewed und somit Missverständnisse aufgedeckt werden.

Quellen