Das PHP-Tool Behat sorgt nun schon seit einiger Zeit für Aufmerksamkeit. Zunehmend findet dadurch in der PHP-Community eine Sensibilisierung für das Thema Behavior Driven Development (BDD) statt. Mit JBehave und insbesondere Cucumber existierten zwar schon vor Behat ähnliche BDD-Frameworks für andere Programmiersprachen, aber erst seit Behat scheint es BDD – zumindest als Begriff – in den Fokus von Webentwicklern geschafft zu haben. Speziell im Fall von Webanwendungen, die in aller Regel sehr “UI-lastig” sind, bietet sich BDD an, um automatisierte Abnahmetests zu erstellen, die über Unit Tests und Integrationstests hinausgehen. Aber ist das Praktizieren von BDD eigentlich gleichbedeutend mit dem Erstellen von automatisierten Abnahmetests? Und ist BDD eine Praktik, eine Methode oder einfach nur eine abstrakte Denkschule? Wie passt Behat in das Ganze rein?

YMC ist der Ansicht, dass um diese Fragen viel Verwirrung herrscht. Wir wollen daher an dieser Stelle für etwas Aufklärung sorgen und erst einmal das Konzept hinter dem Tool verständlich machen – getreu unserer Praxis, ein Tool nicht einfach “ohne Sinn und Verstand” einzusetzen.

Den Code-affinen Entwickler können wir getrost beruhigen, falls dieser Blogpost zu abstrakt erscheinen sollte: Uns konkret mit Behat(-Code) befassen wollen wir dann in einem Folge-Blogpost.

 

Automatisierte Abnahmetests – pragmatisch gesehen

Wenn es darum geht, Abnahmetests für PHP-Webanwendungen zu automatisieren, um sich den langwierigen Prozess händisch durchgeführter Tests zu ersparen, ist Mink erste Wahl hierfür. Dieses Framework für “Web Acceptance Testing” ist Teil des Behat-Frameworks. Ob nun unabhängig von Behat oder zusammen mit Behat eingesetzt, lassen sich damit Interaktionen des Benutzers mit dem Browser simulieren. Dabei greift Mink auf Testing-Tools wie Selenium, Sahi oder Goutte zurück und abstrahiert die APIs all dieser Tools in Form eines einzigen generischen API. So lassen sich automatisierte Abnahmetests unter weitgehender Unabhängigkeit zu einem bestimmten Tool implementieren, was sich insbesondere auf deren Langlebigkeit günstig auswirkt. Allerdings ist Mink nicht ohne Grund von Anfang an als integraler Bestandteil eines BDD-Frameworks entwickelt worden. Man sieht also schon an den technischen Gegebenheiten, dass es bei BDD nicht nur um das Implementieren von automatisierten Abnahmetests geht. Dafür allein würde nämlich schon Mink in Kombination mit PHPUnit vollumfänglich ausreichen.

Die unglückliche Geburt von BDD

BDD wurde 2003 von Dan North als Weiterentwicklung von Test Driven Development (TDD) vorgestellt. Hierfür führte er zunächst syntaktische Konventionen für Unit Tests ein: Die Namen von Testmethoden sollten jeweils aus einem ganzen Satz bestehen und das Verb “test” sollte dabei um das Hilfsverb “should” ergänzt werden. Während die Methode testFindsCustomerById() bspw. gegenüber testCustomerById() zweifelsfrei einer erhöhten Verständlichkeit dient, erschliesst sich Dan Norths ursprüngliche Absicht hinter dem Wörtchen “should” nicht ohne Weiteres. In der Tat scheint testShouldFindCustomerById() auf den ersten Blick kein sinnvollerer Methodenname als testFindsCustomerById() zu sein.

Dan Norths Absicht hinter “should” gegenüber “test” war aber auch eher subtilerer Natur: Eine Schärfung des Bewusstseins dafür, dass es bei TDD nicht um das Entwickeln von automatisierten Tests als Selbstzweck geht (d.h. eine möglichst hohe Testabdeckung zu erreichen), sondern dass man ein bestimmtes Verhalten eines Software-Moduls sicherstellen möchte. Was rückwirkend auf das getestete Modul zumeist auch den Einfluss haben sollte, dass dieses – durch entsprechende Überarbeitungen – gängigen objektorienteren Design-Prinzipien wie bspw. dem Single-Responsibility-Prinzip nachkommt. Das führte schnell dazu, dass BDD als “TDD done right” wahrgenommen wurde. Wie Dan North selbst später feststellten musste, wirkte sich diese Pauschalisierung zusammen mit der teils pedantisch wirkenden Aversion gegen das Wort “Test” nicht unbedingt günstig auf die ersten Stunden von BDD aus: BDD wurde zunächst als eine reine TDD-Praktik wahrgenommen, und nicht als das, als was es eigentlich gedacht war…

BDD als agile Methode

Losgelöst von dem anfänglichen Schwerpunkt auf Unit Tests, lässt sich BDD auch als agile Methode (und nicht nur Praktik) ansehen – dank Tools wie Cucumber und Behat heute mehr denn je. Im Kern von BDD geht es natürlich auch aus Methoden-Sicht weiterhin um das Verhalten eines Stücks Software – nun allerdings etwas anders angegangen: Die Fragestellung, was genau eigentlich zu testen ist, tritt stärker in den Vordergrund. Das Verhalten wird hierfür nun explizit aus Sicht des Benutzers betrachtet wird und das Stück Software muss auch nicht mehr zwangsweise ein einzelnes Modul sein. Das Verhalten wird im Fall der sogenannten Szenario-orientierten Variante von BDD (“StoryBDD”), auf welcher Behat beruht, in Form von Szenarien beschrieben, wofür im Idealfall eine User Story als Basis dient: Zu bzw. statt Abnahmekriterien schreibt man Szenarien in einerDomänenspezifischen Sprache (DSL). Diese DSL besteht im wesentlichen aus den drei Schlüsselwörtern Given, When, Then, die jeweils einem in “Prosa” verfassten Schritt vorangestellt werden. Eine Sequenz solcher Schritte ergibt das Szenario, das mit einer semantischen Struktur versehen ist:

Given a precondition
When an event occurred
Then an outcome is achieved

Abgesehen von den vorgegebenen Schlüsselwörtern gilt für den Prosa-Teil, dass dieser in der “Sprache des Kunden” (und nicht der des Entwicklers) geschrieben werden sollte. Ein klassisches Beispiel, an dem das Schreiben eines Szenarios gut verdeutlicht werden kann, ist die Bankomat-User-Story von Dan North, mit der er einst das Konzept von BDD eingeführt hat:

As an Account Holder I want to withdraw cash from an ATM so that I can get money when the bank is closed

Ein offensichtliches Abnahmekriterium ist, dass Geld erfolgreich abgehoben werden kann, sofern der Bankkunde liquide ist und der Bankomat imstande ist entsprechend viel Bargeld auszugeben. Als Szenario beschreibt das Dan North folgendermassen:

Given the account balance is \$100
And the card is valid
And the machine contains enough money
When the Account Holder requests \$20
Then the ATM should dispense \$20
And the account balance should be \$80
And the card should be returned

Automatisierte Abnahmetests – nach BDD erstellt

Auch wenn wir als praxisorientierte Agilisten nach wie vor automatisierte Abnahmetests als Ziel haben, sind diese nach BDD-Philosophie eher Artefakte, die eigentlich nur nebenbei “abfallen”. Beim Praktizieren von BDD soll die Fragestellung was zu testen ist tatsächlich nämlich primär dem besseren Verständnis von den Software-Anforderungen dienen (die im Detail oftmals auch dem Kunden selbst nicht bekannt sind). So hat Dan North in einer Forendiskussion prägnant klargestellt:

“BDD is about understanding the customer’s need […] (and being able to prove that with an evolving suite of acceptance tests)”

Dieser Aspekt ist auch interessant, wenn es darum geht, den vermeintlichen Mehraufwand für BDD gegenüber “reinen” Test-Praktiken wie z.B. derTest-First-Praktik von XP zu rechtfertigen. BDD führt im günstigen Fall nicht nur dazu, dass man etwas korrekt umsetzt und dies mit automatisierten Tests absichert, sondern auch dass man das Richtige umsetzt (und dies mit automatisierten Tests absichert). Im weiteren Sinne kann man diesen Ansatz von BDD gar als agile Variante der Anforderungserhebung ansehen. Agil ist sie schon allein deswegen, weil für das Schreiben der Szenarien eine enge Zusammenarbeit mit dem Kunden (und weiteren Projekt-Stakeholdern) notwendig ist, und somit mindestens einer der vier agilen Werteunmittelbar in die Tat umgesetzt wird.

Natürlich braucht es allein für die Anforderungserhebung keine Formalisierung der Szenarien in einer DSL. Und die Szeniaren zusammen mit dem Kunden erst einmal in “gesprochener Sprache” niederzuschreiben, anstatt sich (und den Kunden) gleich mit “Grammatik” zu befassen, ist sicherlich die schneller zum Ziel führendere Vorgehensweise. Aber schlussendlich hat man mit in der DSL verfassten Szenarien ausführbare Spezifikationsartefakte:  Die “Givens”, “Whens” und “Thens” verleihen eine Struktur, die es ermöglicht die Beschreibung mit einem entsprechenden Tool leicht zu parsen und zu interpretieren – d.h. “auszuführen”. Während das Parsen von Behat übernommen wird, ist das Interpretieren die eigentliche Schwierigkeit bei StoryBDD. Zumindest für den Entwickler, der mit einer entsprechenden Implementierung sicherstellen muss, dass alle Vorbedingungen erfüllt sind, dass die Benutzerinteraktionen (korrekt) simuliert werden, und dass die erwarteten Folgen eintreten.

Fazit

Schlussendlich können wir feststellen, dass BDD mehr ist als nur automatisierte Abnahmetests zu erstellen. Im Idealfall praktiziert man BDD als Methode in einem agilen Entwicklungsprozess, bei dem Tests als Artefakte erwünscht oder erfordert sein mögen, nicht aber im Vordergrund stehen. Vorrangig geht es darum, die richtigen Anforderungen zu erheben und diese korrekt umzusetzen. Anderns angegangen stellt BDD eher einen Prozess-Overhead dar. In diesem Fall macht der Einsatz von Behat als Tool auch keinen Sinn mehr, hierfür reicht dann allein Mink aus.

0 Kommentare

Einen Kommentar abschicken

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.