Behavior Driven Development – Vom Use-Case zum Test-Case – Behavior Driven Development



Behavior Driven Development – Vom Use-Case zum Test-Case – Behavior Driven Development

1 0


presentation-bdd

A Presentation about BDD

On Github thred / presentation-bdd

Behavior Driven Development

Vom Use-Case zum Test-Case

http://thred.github.io/presentation-bdd/

Behavior Driven Develoment

Vom Use-Case zum Test-Case

  • Methode der agilen Softwareentwicklung
  • Zusammenarbeit verbessern
  • Automatisierte Tests als Benefit

Behavior Driven Develoment ist eine Methode der agilen Softwareentwicklung und hat das Ziel die Zusammenarbeit der Beteiligten zu verbessern. Außerdem sollen aus dieser Zusammenarbeit automatisierte Tests als Benefit entstehen.

Hinweise zu dieser Präsentation:

T drücken um diesen Text zu verstecken bzw. zu zeigen.

C drücken um die Navigationshilfen zu verstecken bzw. zu zeigen.

Mit SPACE zur nächsten Folie wechseln.

Behavior Driven Development

Theorie & Praxis

Übersicht

  • Was ist BDD?
  • Wie funktioniert BDD?

Dieser Vortrag konzentriert sich auf folgende zwei Punkte:

Was ist BDD (Behavior-Driven Development) eigentlich?
  • Was sind die Vorteile und Ziele von BDD?
  • Woraus ist BDD entstanden?
  • In welchem Bereich der Entwicklung ist die Vorgehensweise angesiedelt?
  • Wie wird BDD umgesetzt?
Wie funktioniert die Umsetzung von BDD in der Praxis?
  • Wie sieht der typische Entwicklungsprozess aus?
  • Wie werden Stories verarbeitet?
  • Wie werden Tests umgesetzt?
  • Woraus lassen sich Vorteile ziehen?

Manfred Hantschel

Software Entwickler, Porsche Informatik GmbH

Manfred Hantschel

  • Softwareentwickler bei Porsche Informatik
  • seit 15 Jahren Entwickler
  • seit 2011 BDD

Mein name ist Manfred Hantschel und ich bin Softwareentwickler bei der Porsche Informatik GmbH in Salzburg.

Meine Aufgaben reichen von der technischen Umsetzung und Leitung bis hin zur Produktverantwortung für mehrere Projekte. Die Palette der Applikationen reicht dabei von internationalen webbasierten Unternehmensportalen, über PDA- und Smartphone-basierten Applikationen für die Unterstützung von Händlern, bis hin zu Verwertungsplattformen für Neu- und Gebrauchtfahrzeuge.

Seit 2011 setze ich mich, unter Anderem, mit dem Thema Testautomatisierung und mit der Einführung von Behavior Driven Development auseinander. Die Methodik wird in der Porsche Informatik bei mehreren Projekten – teilweise Webapplikationen, teilweise Client-Server-Applikationen auf Java-Basis – eingesetzt.

Methode der agilen Softwareentwicklung

Theorie

  • Methodik
  • Dan North, 2006
  • TDD verbessern → nicht im Designprozess
  • BDD löst Probleme und geht weiter

Entstanden ist BDD ursprünglich aus dem Test-Driven Development. Es wurde zum ersten Mal 2006 von Dan North beschrieben (siehe "Introduction BDD" von Dan North und http://behaviourdriven.org/)

Er bemerkte, dass TDD oft nicht erfolgreich war. TDD wurde zwar umgesetzt, aber eher als Last empfunden, da TDD nicht in den Designprozess integriert wurde.

BDD versucht nun die Probleme zu lösen und geht dabei einen guten Schritt weiter.

Bessere Zusammenarbeit

Entwickler
QS
Kunde

Bessere Zusammenarbeit

In erster Linie soll die Zusammenarbeit zwischen

verbessert werden. Aus dieser Zusammenarbeit soll dann TDD als Benefit entstehen.

Domain-Driven Design

Test-Driven Development

Vereinigung zweier Prinzipien

Vereinigung zweier Prinzipien

  • Domain-Driven-Design
    • Konzentration auf Fachlogik anstatt Technik
    • Komplexe fachliche Zusammenhänge zerteilen
    • vereinfachte Problemlösung
    • Entwickler sehen nur Teilbereich
  • Test-Driven-Development
    • Konzentration auf das Problem
    • Frühe Designentscheidungen
    • Abstrakte Serviceschichten

Behavior-Driven Development versucht die Prinzipien von Domain-Driven Design mit denen von Test-Driven Development zu vereinen.

Domain-Driven Design

→ next fragment Domain-Driven Design legt den Schwerpunkt der Softwareentwicklung auf die Fachlogik der Anwendung anstatt auf die technische Umsetzung. Die komplexen fachlichen Zusammenhänge werden zunächst in einer Geschäftslogikschicht abgebildet und erst dann werden die Teilbereiche umgesetzt.

In der Praxis bewährt sich der DDD Ansatz im höchsten Maße. Durch die Schichtenarchitektur generell wird die Problemlösung vereinfacht und die Arbeitsteilung erleichtert. Leider laufen Entwickler aber auch Gefahr die eigentliche Aufgabe aus den Augen zu verlieren, weil sie nur den eigenen Teilbereicht wirklich kennen. Jede einzelne Umsetzung ist toll, aber das Ganze hilft dem Benutzer nicht.

Test-Driven Development

→ next fragment Test-Driven Development soll ja den Entwickler dazu anhalten einen evolutionären Prozess in der Entwicklung einzuhalten. Es soll den Entwickler dazu bringen, sich in erster Linie um das Problem selbst zu kümmern, und nicht nur um die Umsetzung einer Lösung. Dazu soll der Entwickler vor der Umsetzung zuerst Tests dazu schreiben.

In der Praxis ist das leider nicht so einfach. Unit-Tests fokussieren den Entwickler schon sehr stark auf die Umsetzung der Lösung. Konzentriert sich der Entwickler zuerst auf Unit-Tests wird er schon frühzeitig mit Problemen konfrontiert, die technische Entscheidungen fordern. Mit Integrations-Tests verhält es sich etwas besser, jedoch decken diese meist nur die Serviceschicht ab ohne auf Details der eigentlichen Aufgabenstellung einzugehen.

Und wie für Domain-Driven Design, gilt auch für Behavior-Driven Development: BDD ist nicht nur eine Technik, BDD ist eine Methode der Softwareentwicklung.

BDD für's Domain-Driven Design ...

standardisierte Sprache für fachlichen Ablauf

Beschreibt:

User-Stories

Akzeptanzkriterien

Story:

As a <ROLE>
I want <FEATURE>
in order to <BENEFIT>
                                
Feature:

Given <PRECONDITION>
When <ACTION>
Then <POSTCONDITION>
                                

→ findet frühzeitig fachliche Fehler

BDD für's Domain-Driven Design ...

  • standardisierte Sprache für fachliche Abläufe
    • → User-Stories
    • → Akzeptanzkriterien
  • einfache Sprache, nur fachlich
  • logisch ausgereift

Für das Domain-Driven Design stellt BDD eine Sprache zur Verfügung, mit der es möglich ist die fachlichen Abläufe detailliert und standardisiert zu formulieren. Mit Hilfe der Sprache lassen sich User-Stories verfassen und Akzeptanzkriterien definieren.

Die Sprache orientiert sich dabei am Benutzer selbst und ist für alle Beteiligten verständlich. Bei der Beschreibung wird gänzlich auf technische Feinheiten verzichtet, lediglich dem fachlichen Ablauf wird ein logischer Prozess zugrunde gelegt.

Und bereits da werden viele Probleme gelöst. Aus meiner Erfahrung tauchen hier oft schon die großen Probleme der Umsetzung auf – nämlich dann wenn der fachliche Prozess schon nicht logisch ausgereift ist. Die Entwicklung kann fast alles umsetzen, einzige Vorbedingung: die Aufgabe muss deterministisch sein. Für die Formulierung des Akzeptanz-Tests muss das Problem auf einem Level beleuchtet werden, das logische Probleme frühzeitig zu Tage fördert.

BDD für's Test-Driven Development ...
Feature: Sales list

As a manager
I want to list all employees
in order to select and edit one.

Scenario:

Given the list of employees is displayed
When I click on the name of an employee
Then the detail page should be opened.
                                

→ Schlüsselwörter

Akzeptanz-Tests

Konzentration auf das Problem

Umsetzung kann ignoriert werden

Eingehen auf fachliche Details

BDD für's Test-Driven Development ...

  • Werkzeug: Akzeptanz-Tests
  • konzentration auf Problem
  • fachliche Ebene (anders als Unit-Tests)

Für das Test-Driven Development stellt BDD ein Werkzeug zur Verfügung - nämlich Akzeptanz-Tests.

Akzeptanz-Tests konzentrieren sich, wie von TDD gefordert, auf das Problem selbst. Die Umsetzung der Lösung kann zunächst vollkommen ignoriert werden. Die Tests bewegen sich auf einer rein fachlichen Ebene, anders als Unit-Tests. Trotzdem ist es möglich, ja gefordert, auf fachliche Details einzugehen.

Durch die Schlüsselwörter ist es möglich die Akzeptanz-Tests automatisch zu verarbeiten und programmtechnisch Tests auf Grundlage der Kriterien verfassen.

Test-Quadranten

Test Quadranten

  • Brian Marick, Lisa Crisping
  • Fachlich / Technisch
  • Unterstützt das Team / Kritisiert das Produkt

Die Testquadranten von Brian Marick und in erweiterter Form von Lisa Crispin geben eine gute Orientierungshilfe in Bezug auf verschiedene Testarten.

Im Wesentlichen werden Tests nach 2 Ebenen kategorisiert:

Fachlich vs. Technisch geprägt

Die Unterscheidung zwischen technisch und fachlich geprägt kann man am leichtesten treffen, wenn man sich das Zielpublikum vor Augen hält mit dem man über einen Test spricht bzw. sich Gedanken macht, wer denn einen Test durchführen könnte. In einem technisch geprägten Test werden die Durchführenden wohl eher Entwickler sein wogegen bei fachlich geprägten Tests ein Tester oder vielleicht der Product-Owner selbst der Durchführende sein können.

Unterstützt das Team / Kritisiert das Produkt

Man könnte auch sagen "vor der Entwicklung" und "nach der Entwicklung".

Entwickler die Erfahrungen mit Test-Driven-Development (TDD) gemacht haben, berichten oft, dass sie ihre Systeme/Klassen anders (einfacher) gestalten wenn die Tests vorher geschrieben werden – somit unterstützen diese Tests das Team während der Entwicklung. Außerdem werden durch die ständige Durchführung der Tests Seiteneffekte sofort entdeckt – eine weitere, nicht unwesentliche, Unterstützung.

Tester haben an und für sich einen destruktiven Job – sie versuchen das System zu brechen bzw. Fehler zu finden. Wenn ihnen das nicht gelingt, kann man mit hoher Wahrscheinlichkeit davon ausgehen, dass das System robust ist und die getesteten Funktionalitäten gewährleistet sind. Somit versuchen sie, das Produkt zu kritisieren und Schwachstellen aufzudecken.

Test-Quadranten

Test Quadranten

  • Explorativ, Usability, Abnahme
  • Unit-Tests
  • Performance-Tests
  • Akzeptanz-Tests

Versucht man nun die verschiedensten Testarten in dieses System einzuordnen, fällt das relativ leicht:

Exoploratives Testen, Usability Tests, Kundenabnahme

Diese Arten von Tests – meist manuell durchgeführt – versuchen Fehler im System zu finden, kritisieren also das Produkt. Auf der zweiten Ebene betrachtet sind diese Tests aber ausschließlich durch fachliche Anforderungen geprägt – man testet also gegen die fachliche Spezifikation.

Unit-Tests, Komponenten-Tests, ...

Wenn man Unittests & Co nach TDD schreibt, unterstützen sie das Team bei der Arbeit indem sie Einfluss auf die Systemarchitektur haben und Seiteneffekte sehr schnell erkannt werden. Allerdings sind sie technisch geprägt, werden also durch Entwickler entworfen und geschrieben.

Performance- und Last-Tests, Skalierbarkeitstests, ...

Auch diese Tests versuchen das Produkt zu kritisieren indem sie die nicht-funktionalen Anforderungen in Frage stellen. Sie sind technisch geprägt da ein Product-Owner wohl kaum in der Lage sein würde solche Tests zu entwickeln.

Prototypen, Simulation, Akzeptanz Tests

Last but not least sind Vorgehensweisen wie Prototyping, Storyboards & Co sowohl fachlich geprägt als auch unterstützend für das Team. Eine (oft viel zu wenig beachtete) Grundregel in der Softwareentwicklung besagt: Je besser eine Anforderung vorbereitet und durchdacht ist, umso einfacher wird die Entwicklung. Hier ist auch das Behaviour-Driven-Development anzusiedeln!

1. Fallbeispiele

Leitfaden für die Umsetzung

Leitfaden für die Umsetzung

Fallbeispiele

  • Entwicklungsprozess?
  • Fallbeispiele

Wie kann man sich nun vorstellen, dass BDD im Entwicklungsprozess umgesetzt werden kann?

Zunächst werden die Anforderungen textuell durch Fallbeispiele beschrieben.

Fallbeispiel = User-Story

genau ein Anwendungsfall

ideal aus Benutzersicht

User-Story: Add article to cart

As a customer
I want to select an article
in order to put it into my shopping cart.
                    

→ vermeidet Redundanz in Lasten- und Pflichenheft, Use-Cases und Konzepten

Fallbeispiel = User-Story

  • Anwendungsfall aus Sicht des Benutzers
  • Sprache die alle verstehen, denn:
    • Lasten- und Pflichtenheft → Kunde
    • Use-Case → QA
    • Konzept → Entwickler

Fallbeispiele haben einen anderen Fokus als Use-Cases, Konzepte, Protokolle, Lasten- oder Pflichtenhefte: Fallbeispiele beschreiben genau einen Anwendungsfall aus der Sicht eines Benutzers. Wir schreiben Applikationen für Benutzer und darauf liegt der Fokus.

Klar, wir können auch Lasten- und Pflichtenhefte scheiben, aber die sind für Kunden. Wir können auch Use-Cases scheiben, aber die sind für Tester. Wir können auch Konzepte schreiben, aber die sind für Entwickler. Unser Ziel ist eine Sprache zu sprechen, die alle verstehen, und daher schreiben wir User-Stories.

User-Stories als Sprintziele

User-Stories als Sprintziele

  • Sprintziele

Und weil wir agil entwickeln, brauchen wir die User-Stories sowieso, nämlich als Sprintziele. Aber erst durch BDD finden die User-Stories wirklich Einzug in unser Projekt, da sie maschinell verarbeitet werden müssen.

2. Akzeptanzkriterien

Leitfaden für die Umsetzung

Leitfaden für die Umsetzung

Akzeptanzkriterien

  • Fallbeispiele → Akzeptanzkriterien

Als nächster Schritt werden die Fallbeispiele um Akzeptanzkriterien erweitert und automatisiert.

Akzeptanzkriterien = Scenarios

mehrere Szenarien je User-Story

Aktionen eines Benutzers

Sonder- und Problemfälle

Einfachheit ist Trumpf

Scenario: Add article to cart

[...]

Given the detail page of article "ART000042" is displayed
When the user clicks the "Add to Cart" button
Then the added to cart message should appear
And the cart should contain the article "ART000042"
                    

Akzeptanzkriterien = Scenarios

  • Mehrere Akzeptanzkriterien je User-Story
  • Aktionen, Sonder- und Problemfälle
  • Given, When, Then → Automatisierung

Zu jeder User-Story werden mehrere Akzeptanzkriterien verfasst. Diese Scenarios detaillieren die Story, beschreiben Sonder- und Problemfälle und listen mögliche Aktionen des Benutzers auf.

Auch diese User-Stories sind in einer Sprache verfasst, die alle Beteiligten lesen und verstehen können.

Die Texte basieren auf Schlüsselwörtern, im Normalfall "Given", "When" und "Then". Um den Text besser lesbar zu gestalten bieten manche Frameworks auch andere Schlüsselwörter wie z.B. "And" und "But" an. Ebenso bieten die Frameworks das Parsen von Variablen und Tabellen aus den Texten selbst an. Der restliche Text wird 1:1 an das Testframework übergeben.

Abstimmung mit Kunden

Dadurch Einbindung in Entwicklungsprozess

Stories → Werkzeug

fachliche Fehler früh erkennen

Abstimmung mit Kunden

  • Abstimmung Kunde → eingebunden
  • Stories → Werkzeug
  • fachliche Fehler früh erkennen

Die fertigen User-Stories und Akzeptanzkriterien werden mit dem Kunden gemeinsam entwickelt, oder zumindest mit ihm abgestimmt. Der Kunde wird somit in den Entwicklungsprozess mit eingebunden. Hier zeigt sich schon ein weiterer Vorteil. Früher sind fachliche Fehler erst im fertigen Produkt aufgetaucht. Die Stories geben dem Entwicklungsteam ein Werkzeug in die Hand, mit dem der fachliche Ablauf vollständig definiert werden kann.

Wenn man wirklich agil arbeitet, können die Akzeptanzkriterien ein Lasten- und Pflichtenheft zumindest teilweise ersetzen.

Abstimmung mit QA

Frühzeitig eingebunden

Szenarios als automatisierte Testfälle

Ergänzen Testkatalog (aber kein Ersatz!)

Bessere Kommunikation

Abstimmung mit QA

  • QA frühzeitig einbinden
  • Testkatalog ergänzen

Auch die Qualitätssicherung wird frühzeitig in den Prozess eingebunden. Schon das ist ein enormer Vorteil. Oft wird die Qualitätssicherung in Projekten stiefmütterlich behandelt. Die fertige Applikation wird übergeben und die Qualitätssicherung soll schauen wie sie damit zurecht kommt.

Da die Akzeptanzkriterien den Testkatalog ergänzen wird der Qualitätssicherung auch viel Arbeit abgenommen. GUI-Tests werden mit dem Produkt mitgeliefert und muss nicht nachträglich und umständlich definiert werden.

Umsetzung der Tests

Implementation: Given, When, Then

Test-First

Eingebunden in Spezifikations- und Testprozess

Umsetzung der Tests

  • Umsetzung der Tests

Die Entwickler kümmern sich zunächst um die Umsetzung der Tests. Bevor die Applikation fertig ist, könnte sie theoretisch schon getestet werden. Auch hier zeigt sich der Vorteil, dass Entwickler schon frühzeitig in den Spezifikationsprozess eingebunden werden.

3. Umsetzung

Leitfaden für die Umsetzung

Leitfaden für die Umsetzung

Umsetzung

  • Umsetzung

Erst jetzt folgt die Umsetzung der Anforderung.

Umsetzung und Abnahme

Umsetzung nach User-Stories und Akzeptanz-Tests

QA testet zunächst manuell, dann automatisiert

Automatische Spezifikation für Kunden

Umsetzung und Abnahme

  • vollständgie Entwicklung
  • QA einbinden → Testumfang?
  • Testkatalog ergänzen
  • Spezifikation für Kunden

Erst im dritten Schritt wird die Anforderung umgesetzt. Das Entwicklungsteam hat bereits automatische Tests an der Hand.

Die Qualitätssicherung führt die Test zunächst manuell durch, bis klar ist, dass die Szenarien den nötigen Testumfang abdecken. Danach können diese Tests jederzeit automatisch durchgeführt werden.

Als zusätzlicher Benefit kann aus den User-Stories auch automatisch eine Spezifikation der Applikation abgeleitet werden.

In der Praxis

Behavior Driven Develoment

Praxis

  • typischer Entwicklungsprozess
  • Stories / Tests
  • Vorteile

Dieser Vortrag konzentriert sich auf folgende zwei Punkte:

Was ist BDD (Behavior-Driven Development) eigentlich?
  • Was sind die Vorteile und Ziele von BDD?
  • Woraus ist BDD entstanden?
  • In welchem Bereich der Entwicklung ist die Vorgehensweise angesiedelt?
  • Wie wird BDD umgesetzt?
Wie funktioniert die Umsetzung von BDD in der Praxis?
  • Wie sieht der typische Entwicklungsprozess aus?
  • Wie werden Stories verarbeitet?
  • Wie werden Tests umgesetzt?
  • Woraus lassen sich Vorteile ziehen?

Porsche Informatik GmbH

http://porscheinformatik.at

Porsche Informatik GmbH

  • Teil der Porsche Holding
  • über 400 MA in allen Bereichen der IT
  • Softwarelösungen für Automobilhandel
  • BDD in mehreren großen Projekten

Typischer Entwicklungsprozess

1.) Product-Owner formuliert die Idee

2.) Anforderung wird in Datenbank erfasst

3.) Epic aus Anforderungen formulieren

4.) User-Stories für Epics

Typischer Entwicklungsprozess

  • Idee steht am Anfang (Product-Owner, Kunde, Entwicklung)
  • Anforderung erfassen
    • offizielle Statusverfolgung
  • erst Epics, dann User-Stories
  • User-Stories noch nicht ausformuliert

Am Anfang war die Idee. Diese wird meist vom Kunden bzw. dem Product-Owner ausgebrütet und formuliert. Die Idee kann aber auch von anderen Beteiligten kommen, z.B. von der Entwicklung. Die Idee wird bei uns in einer Anforderungsdatenbank, noch in Prosa, erfasst. Die Anforderung enthält eine grobe Vorstellung wie das Feature aussehen soll und beschreibt Hintergrundinformationen.

In der Porsche Informatik wird die Anforderungsdatenbank auch für die offizielle Statusverfolgung genutzt, da sich unsere Kunden mit dem agilen Vorgehen oft noch nicht richtig anfreunden können. Teilweise dient die Anforderungsdatenbank auch als Quelle für Aufwandsschätzungen, besonders wenn die Umsetzung für das nächste Wirtschaftsjahr geplant ist. Auch das deckt sich noch nicht mit dem agilen Vorgehen.

Für große Anforderungen, die nicht in einem Sprint umgesetzt werden können, werden jetzt User Epics verfasst. User Epics sind Sammlungen von User-Stories, es müssen aber zu Beginn nicht alle User-Stories ausformuliert sein.

Vor Umsetzung: Konkretisierung

Alle Beteiligten arbeiten mit

Einfache Fragen stellen

Es Entstehen: Behaviors, Story-Files, UI-Mockups, Aufwände, Schnittstellen, ...

Vor Umsetzung: Konkretisierung

  • Vor Umsetzung: Konkretisierung
  • Beteiligung: Kunde, QA, Entw.
  • einfache Fragen
  • Szenarien noch nicht maschinell verarbeitbar
  • weitere Dokumente: UI-Mockups, Aufwände, ...

Bevor das Feature umgesetzt wird, wird es noch konkretisiert. Dies geschieht durch Kunde, QA und Entwicklung gemeinsam.

Grundsätzlich werden dem Kunden "einfache Fragen" gestellt. Die Ergebnisse aus diesen Abstimmungen werden einem Story-File festgehalten, in Behaviors aufgeteilt und im Versionskontrollsystem eingepflegt. Behaviors entsprechen den Szenarien, müssen jedoch noch nicht so formuliert sein, dass sie maschinell verarbeitet werden können.

Je nach Umfang des Features entstehen auch noch zusätzliche Dokumentation: UI-Mockups, eine Aufwandsschätzung, Schnittstellendokumentationen, usw. Wir achten darauf, dass jede einzelne zusätzliche Dokumentation auch in der Story referenziert ist und die Redundanz so gering wie möglich ist.

Vor Sprint: Formalisierung

Bewertung für Automatisierung: Wichtigkeit, Aufwand, Sinn

Formulierung der Szenarien

User-Story: Add Article to Cart

As a customer
I want to select an article
in order to put it into my shopping cart.

[...]

Scenario: Duplicate Article

Given the shopping cart already contains an article.
When the user selects the same article
And clicks the "Add to Cart" button
Then the cart should contain the article only once
But with a count of 2.

[...]
                    

Vor Sprint: Formalisierung

  • Je Sprint abstimmen
  • Wichtigkeit, Aufwand, Automatisierung
  • Testkatalog

Kurz vor der Sprintplanung wird zwischen Entwickler und Tester abgestimmt, welche Verhaltensweisen man formalisieren und automatisieren will.

Entscheidungskriterien dabei sind:

  • Wie wichtig ist das Behavior?
  • Wie oft müsste es getestet werden?
  • Wie aufwendig ist die Automatisierung?

Auf Basis dieser Entscheidungen werden dann die Szenarien formalisiert (was rausfällt landet in einem Testkatalog).

Stationen eines Feature-Files

Stationen eines Feature-Files

  • Verzeichnisse
  • Dokumentation automatisieren

Im Entwicklungszyklus durchwandert ein Story-File (jetzt Feature-File) dann mehrere Stationen. Diese sind als Verzeichnisse im Repository abgebildet. Grundsätzlich wird zwischen Stories unterschieden, die sich in Entwicklung befinden und jenen, die fertig umgesetzt wurden und Teil der Systemspezifikation werden.

Zunächst befindet sich ein Story-File in "preparation". Soll die Story im Sprint umgesetzt werden, wird das File in "current" verschoben. Wenn die Umsetzung erledigt wurde, wird das File in "finished" verschoben.

→ next fragment Nach dem Sprint wird das Story File in den "Feature-Tree" eingepflegt. Der "Feature-Tree" ist nach den Modulen im System aufgebaut. Die Übernahme erfolgt entweder durch kopieren der Datei oder durch händisches Anpassen von bestehen Story-Files.

In einem Projekt der Porsche Informatik wird der "Feature-Tree" sogar dazu verwendet, automatisch eine Systemspezifikation zu generieren. Dazu werden die Story-Files und zusätzliche Dateien im "Feature-Tree" zu einem Dokument zusammengefasst. Dieser Prozess ist leider sehr aufwendig, das Ergebnis ist jedoch beachtlich: Jede Version enthält eine getestete und exakte Systemspezifikation als PDF Dokument.

Umsetzung

@Given("the user $name is logged in")
public void ensureUserLoggedIn(String name)
{
    User user = userService.getCurrentUser();

    if (!name.equals(user.getName()))
    {
        userService.logout();
        userService.login(name);
        user = userService.getCurrentUser();
    }

    assert name.equals(user.getName());
}
                        

Umsetzung

  • Steps-Klassen
  • Robustheit und Aufwand problematisch

Wie erfolgt nun die Anbindung der Szenarios an die Applikation?

Grundlegend ganz einfach: in Steps-Klassen werden die Texte aus den Szenarien implementiert. Das Beispiel zeigt wie das grundsätzlich funktionieren könnte. Doch in dieser Art und Weise läuft man schnell Gefahr, dass die Wartungsaufwände für die BDD-Tests zu hoch werden.

Daher haben wir in diesem Bereich viel Energie investiert um die Tests robust zu gestalten.

Umsetzung

@Autowired
private UserWorkflow userWorkflow;

@Given("the user $name is logged in")
public void ensureUserLoggedIn(String name)
{
    User user = userWorkflow.login(name);

    assert name.equals(user.getName());
}
                        

Umsetzung

  • Workflows für Aktionen
  • Modulübergreifend
  • Wiederverwendung
  • Aufbau von Testdaten
  • Testinterface

Grundsätzlich agieren die Steps nun auf Workflows. Erst die Workflows führen die Aktionen in der Applikation durch. Workflows agieren modulübergreifend, können daher auf die Schnittstellen der gesamten Applikation zugreifen. Die Logik wandert dadurch aus den Steps heraus und die BDD-Tests werden stabiler. Ähnliche Verhaltensweisen müssen auch nicht mehrfach implementiert werden.

Mit dieser Technik werden auch Testdaten aufgebaut. Die Tests müssen nicht auf einer vorbereiteten Datenbank laufen, sie erstellen die nötigen Testdaten selbst. Robustheit ist der Schlüssel.

Das Testinterface ermöglicht uns auch Aktionen auszuführen, die in der Applikation eigentlich nicht möglich wären, z.B. einen Benutzer zu löschen anstatt nur ein "gelöscht"-Flag zu setzen.

Bleibt aber immer noch das Problem die GUI zu steuern.

Umsetzung

Umsetzung

  • Pages und Components
  • Kommandos via Driver-API
  • Selenium
  • Applikationsübergreifend

Um die GUI zu Steuern erzeugen wir für die Ansichten und Wartungen in der Applikation, Pages und Komponenten. Die Klassen beschreiben beispielsweise die Felder einer Login-Seite, also z.B. "Benutzername", "Passwort" und den "Anmelden" Button. Zentrale Komponenten, wie z.B. einen Suchdialog, werden in Component Klassen definiert, damit diese in mehreren Pages zur Verfügung stehen.

Die Pages interagieren über eine eigene Driver-API mit der GUI. In der API stehen die gängigsten Kommandos für die Automatisierung zur Verfügung, als z.B. "Klicke auf ein Element", "Fülle Feld X mit Y". Diese API soll uns ermöglichen auf Versionsupdates und Änderungen im Automatisierungstool zu reagieren.

Der Driver ist nun die spezielle Implementierung eines Automatisierungstools - in unserem Fall: Selenium 2.x (Webdriver). In den Driver ist auch eine Application Map integriert. Sollte das Mapping von z.B. Feld-Name auf Feld-Id nicht automatisch möglich sein, kann dieser Definition ein Mapping hinterlegt werden.

Die API und der Driver werden applikationsübergreifed eingesetzt.

Was haben wir erriecht?

Anpassungen nur an einer Stelle

Wiederverwendung der Workflows, Components und Pages

Mapping unterstützt Test-Driven-Development

Automatisierungstool ist austauschbar

Was haben wir erriecht?

  • Wartungsproblem im Griff
    • Anpassungen nur an einer Stelle
    • Wiederverwendung
  • vorab automatisieren

Mit diesem scheinbar sehr komplexen Framework versuchen wir dem Wartungsproblem bei der Testautomatisierung in den Griff zu bekommen. Wenn man das Framework nochmal genau betrachtet, stellt man schnell fest, dass der Aufwand ein neues Scenario zu automatisieren darin besteht, die betroffenen Pages und deren Verbindung untereinander zu beschreiben.

Zudem haben viele Scenarios dieselben oder zumindest sehr ähnliche Vorbedingungen – es stellt sich also sehr schnell der Vorteil der Wiederverwendung ein.

Durch die Abstraktionsebenen und das automatische Mapping von abstrakten Feldbezeichnungen auf ID’s ist es nun auch problemlos möglich, GUI-Tests vorab zu automatisieren. Im Idealfall werden die Steps nun während der Entwicklung "grün”.

Do's & Don't's

Nicht alles automatisieren

KISS

Robustheit, Robustheit, Robustheit

BDD ist mehr als automatisierte GUI-Tests

Do's & Don't's

  • Nicht alles automatisieren
  • KISS - z.B. Datumsfeld
  • Robustheit
  • BDD ist mehr als automatisierte GUI-Tests

Nicht alles automatisieren

Je mehr man automatisiert, umso mehr muss man auch pflegen. Selbst wenn man ein ausgeklügeltes Framework verwendet, Anpassungen wird es immer geben. BDD kann sowieso keine erfahrene QA-Abteilung ersetzen, also sollten wir in erster Linie essentielle Teile der Applikation testen. Wir nennen das Positiv-Tests.

Szenarien müssen lesbar bleiben

Verketten Sie nicht unzählige Vorbedingungen in einem Scenario nur weil es die Steps schon gibt. Verstecken Sie die Komplexität lieber in der Implementierung der Steps und formulieren Sie aussagekräftige Steps.

Machen Sie sich das Leben so leicht wie es geht

Je komplizierter der Weg vom Scenario bis zur fertigen Automatisierung ist, umso schwieriger wird es sein, ihre Entwickler zum Mitmachen zu bewegen.

Vergessen Sie nicht auf die Wartbarkeit zu achten

... steht etwas im Widerspruch zur obigen Aussage. Wenn man aber Steps mit Record&Replay Scripten automatisiert, ist man schnell in der Wartungsfalle und kommt nur unglaublich schwer wieder heraus.

Robustheit, Robustheit, Robustheit

Achten Sie bei Tests auf ihre Robustheit. Kein Test geht von Vorbedingungen aus, die nicht spezifiziert sind. Will ich einen Artikel verkaufen, muss ein verkaufbarer Arktikel verfügbar sein. Das "Given" überprüft ob ein solcher Artikel vorhanden ist, legt wenn nötig einen an und merkt sich die Id, damit der Artikel im "When" verkauft werden kann. Stories sollten ihre Testdaten aufräumen, und wenn die eigenen Testdaten zu Beginn schon in der Datenbank sind, trotzdem laufen.

BDD ist mehr (als automatisierte GUI-Tests)

Die GUI-Tests, die anhand der Feature-Files ablaufen sind beeindruckend. Leider wird aber BDD oft auf dieses Feature reduziert. Wird weder der kommunikative Ansatz genützt noch das "Test-First"-Prinzip eingehalten kann man kaum mehr von BDD sprechen. Dann ist es den Aufwand auch nicht mehr wert die Feature-Files zu pflegen; es reicht mit Selenium GUI-Tests zu implementieren.

Integration

Behavior Driven Development

Integration

  • Builds
  • Laufzeit
  • Testdaten

Wie fügt sich das Ganze jetzt in die technische Infrastruktur ein? Wie sieht es mit der Laufzeit aus? Woher bekommen wir Testdaten?

Builds

Automatisierte Builds

Build → Test → Deployment → Akzeptanz-Tests → Documentation

Lokale Tests

Gegen Entwicklungsumgebung

Gegen Ad-Hoc Server

Builds

  • In Jenkins-Build integriert
  • Problembenachrichtigung
  • Ad-Hoc Server

Wir verwenden Jenkins als CI-Umgebung. Dieser führt mehrmals am Tag einen vollständigen Build durch und deployt die Applikation automatisch auf ein Testsystem. Sobald der Applikationsserver gestartet worden ist, beginnt der Akzeptanz-Test. Bei Fehlern werden sowohl der Product-Owner als auch der zuständige technische Architekt per Email verständigt.

Anschließend wird noch die aktuelle Systemspezifikation generiert.

Dieses Vorgehen ist durch das Buch [Continous Delivery] inspiriert.

Natürlich können Entwickler Tests auch lokal durchführen. Dabei spielt die Robustheit der Tests wieder eine Rolle. Die Tests können selbst die Applikation starten, inkl. InMemory-Datenbank, und die Tests dagegen ausführen.

Laufzeit

Parallelisierung

Mehrere Testumgebungen

@VIP Tag

Laufzeit

  • Parallelisierung möglich
  • Ausführung trennen

Sobald man mehrere Akzeptanz-Tests hat kann die Laufzeit der Tests zu einem Problem werden. Jenkins kann Jobs parallelisieren und die Ergebnisse wieder vereinen. Die Akzeptanz-Tests werden in mehrere Gruppen geteilt und parallel ausgeführt.

Zur Zeit haben wir noch in keinem Projekt große Probleme mit der Laufzeit. Die Parallelisierung haben wir daher erst bei einem Projekt umgesetzt. Da die Tests gegen Oracle laufen sollen, können wir keine echte Ad-hoc Umgebung verwenden, wir brauchen daher vier Testumgebungen, gegen die die Tests laufen (sonst könnte es vorkommen, dass sich die Test beeinflussen).

Sollte es wider Erwarten noch mehr Probleme mit der Laufzeit geben, haben wir für Szenarien @VIP Tags vorbereitet. Im Buildzyklus kann dann definiert werden, dass nur Szenarien ausgeführt werden die mit @VIP gekennzeichnet sind.

Testdaten

Test bereiten Daten selbst vor

Vorbereiten der Datenbank

DDL durch Liquibase

Vorbereiteter Mandant

Migrationsmechanismus

Testdaten

  • Tests bereiten selbst vor
  • Liquibase
  • Migrationsmechanismus

Grundsätzlich ist es so, dass alle Tests ihre Daten selbst vorbereiten. Dies geschieht mit Hilfe der "Given" Anweisungen. Hier ist wieder die Robustheit der Tests ein Thema.

Trotzdem ist es aber nötig, dass die Applikation beim Starten die Datenbank vorbereitet. Die Initialisierung bzw. die Aktualisierung erfolgt dabei durch Liquibase. Dann ist es noch notwendig eine Grundkonfiguration zu erstellen, also z.B. einen Mandanten für die Tests zu erzeugen.

Schließlich werden noch über einen Migrationsmechanismus, der in der Applikation sowieso existiert, Testdaten eingespielt. Diese Testdaten sind jedoch für die BDD-Tests nicht nötig. Sie dienen lediglich dazu die Umgebungen der Entwickler mit sinnvollen Daten zu befüllen.

Frameworks & Tools

Behavior Driven Development

Frameworkds

  • Empfehlungen

Welche Frameworks und Tools werden bei der Prosche Informatik verwendet?

https://cucumber.io/

Verwaltet Feature-Files

Test-Framework Anbindung

Java, Ruby, .Net, Flex, ...

Cucumber

  • Feature-Files
  • Cucumber-JVM
  • JUnit / TestNG → IDE Integration
  • Plugins: Reports, Spring, ...

Cucumber ist das Framework, welches die Feature-Files verwaltet, liest und als Test ablaufen lässt. Cucumber steht dabei in mehreren Varianten zur Verfügung. Die Basisversion wurde für Ruby erstellt. Sehr bald gesellte sich aber Cucumber-JVM dazu, das rein in Java entwickelt wurde und die Hürden der Verwendung das Ruby-Frameworks beseitigte.

Cucumber liest die Feature-Files und erstellt daraus JUnit bzw. TestNG Testfälle. Dadurch ist die Integration zu allen wichtigen Tools wie IDEs und Buildtools vorhanden. In Eclipse oder IntelliJ z.B. lassen sich Feature-Files einfach als Unit-Tests starten.

Weiters stellt Cucumber noch eine Menge weiterer Module und Plugins zur Verfügung: Spring-Integration, HTML-Reports, Android Unterstützung, OSGI Unterstützung, u.v.m.

Andere BDD Frameworks

JBehave: Ähnlich zu Cucumber-JVM

JDave: Java-Files als Feature-File

easyb: Groovy-basiert

Gherkin: Sprachdefinition/-parser für Feature-Files

Andere BDD-Frameworks

  • JBehave
  • JDave
  • easyb
  • Gherkin

JBehave

JBehave ist sehr ähnlich zu Cucumber-JVM. Es ist das ursprüngliche Framework von Dan North. Die aktivere Community scheint aber Cucumber zu haben.

JDave

JDave ist neuer und bietet die Möglichkeit die Feature-Files als Java-Klasse zu definieren. Für uns verliert sich hier jedoch die Lesbarkeit der Story-Files.

easyb

easyb basiert auf Groovy. Feature-Files können direkt in Groovy definiert werden.

Gherkin

Gherkin ist kein eigentliches BDD Framework, aber es bietet den Syntax-Parser für Feature-Files und ist daher hier aufgeführt.

Selenium

http://www.seleniumhq.org/

Automatisiert Browser Tests

Mehr-Browser fähig

Konkurrenzlos

Selenium

  • Automatisiert Browser Tests

Cucumber bietet keine Anbindung an einen Web- oder Rich-Client. Die oft referenzierten automatisierten GUI-Tests sind kein Feature der meisten BDD-Frameworks.

Für webbasierte Applikation kann Selenium als Steuerung des Clients verwendet werden. Es startet eine neue Instanz eines Browsers und Instrumentiert die Applikation mit einer Fernsteuerung. Weiters bietet es eine API, auf diese Fernsteuerung, von Javacode aus zugreifen zu können. Damit bietet es die Grundvoraussetzung GUI-Tests zu implementieren.

Liquibase

http://www.liquibase.org/

Automatisiert DDL Änderungen

Versionsverwaltung

XML-basiert und DB-unabhängig

Liquibase

  • DDL Änderungen

Liquibase führt DDL-Changes anhand von XML-basierten Beschreibungsdateien (sog. ChangeSets) durch. In der DB selbst wird vermerkt welche ChangeSets schon eingespielt wurden und welche noch nicht.

Der Vorteil von Liquibase ist, dass, egal welchen Stand die Datenbank hat, diese auf die aktuelle Version gebracht werden kann. Das macht Liquibase dermaßen gut, dass in vielen Applikation keine direkten DDL Änderungen auf der Datenbank nötig sind, weder während der Entwicklung noch beim Einspielen von Updates. Die Zieldatenbank ist dabei egal. Die ChangeSets funktionieren sowohl gegen lokale Inmemory-DBs (z.B. HSQLDB) als auch gegen die großen Konzern-DBs wie Oracle oder DB2.

Cucumber Report DB

https://github.com/porscheinformatik/cucumber-report-db

Verwaltet Testergebnisse

Historische Vergleiche

Highscore

Cucumber Report DB

  • Durch POI Entwickelt

Hausintern werden alle Läufe von Akzeptanz-Tests zentral getrackt. Dadurch ist es möglich die Tests historisch zu vergleichen. Dies ist hilfreich um z.B. Tests mit langer Laufzeit oder geringer Robustheit zu finden.

Das Tool wurde von der Porsche Informatik entwickelt und ist Open Source.

Behavior Driven Development

http://thred.github.io/presentation-bdd/

Conclusio

  • gleiche Sicht
  • Dokumentationsaufwand reduzieren
  • hoher Aufwand
  • Fragen?

Mit BDD können wir schaffen, dass alle Beteiligten die gleiche Sicht auf ein Produkt haben und wir können schaffen, dass wir (redundanten) Dokumentationsaufwand reduzieren.

Am Beginn muss für BDD doch mit einigem Aufwand gerechnet werden. Das rentiert sich nur bei größeren Projekten. Ist das Thema aber bei allen Beteiligten angekommen beginnen sich die Vorteile zu zeigen.

Anhang

Referenzen

Behavior Driven Development

"Introduction BDD" von Dan North: ein Einführung ins Behavior Driven Development

http://behaviourdriven.org/: Webpräsenz speziell zum Thema Behavior Driven Development

BDD in Action: Behavior-driven development for the whole software lifecycle by Smart, John Ferguson (2014) Paperback (ASIN: B00RKQDB4E)

Referenzen