© GreenFlash/Shutterstock.com
TDD und BDD im Praxischeck

Testfalle


Testgetriebene Softwareentwicklung ist weitbekannt, aber noch immer nicht weit verbreitet. Und das, obwohl mit den heutigen Werkzeugen das Entwickeln mit automatisierten Tests kaum einen Mehraufwand bedeutet. Dieser Workshop zeigt, wie leicht sich Test-driven Development (TDD) und Behavior-driven Development (BDD) in den Entwicklungsalltag integrieren.

Reflektiert man einmal das persönliche Vorgehen bei Implementierungsarbeiten, muss man allzu oft eingestehen, dass man Funktionen gegen das Graphical User Interface (GUI) entwickelt. Diese Strategie führt auch zu einem Ziel. Mit fortschreitendem Entwicklungsgrad werden die Funktionstests allerdings sehr schnell mühselig, die stets zu knappe Zeit wird noch knapper. Das Risiko möglicher Fehler wächst unter dem entstandenen Zeitdruck überproportional, und im Allgemeinen verlangsamt sich die Produktivität. Die Idee, gegen Testfälle zu entwickeln, wurde von verschiedenen Autoren unter dem Stichwort „testgetriebene Entwicklung“ in diversen Büchern ausführlich besprochen. Aber was hindert uns daran, diesen Ideen zu folgen und sie zu einem Teil unseres Arbeitsflusses zu machen? Eine naheliegende Antwort ist sicherlich Projektstress, der nicht genügend Freiräume schafft, neue Ideen weiter zu verfolgen. Oftmals sehen sich Entwickler durch die strengen Vorgaben innerhalb der Firmen demotiviert, in ihrem Verantwortungsbereich eigenständig an Verbesserungen zu arbeiten. Vermutlich trägt zur Nichtumsetzung dieser Paradigmen auch bei, dass sie zu großen Teilen an umfangreiche Planungskonzepte gebunden sind. Das widerspricht der Natur eines Entwicklers – der eher eine Frau oder ein Mann der Tat ist – fundamental. Daher wollen wir uns dem Thema Softwaretests ein wenig pragmatischer nähern und dem agilen Gedanken folgen.

Zunächst werfen wir die Idee über Bord, dass erst Testfälle entwickelt werden und dann gegen diese Testfälle implementiert werden soll. Wir betrachten stattdessen die Welt von ihrer unverblümt realen Seite. Eine Anforderung wurde so weit spezifiziert, dass sie von der Projektleitung genehmigt wurde und nun umzusetzen ist. Um nicht allzu abstrakt zu bleiben, bedienen wir uns eines einfachen, aber hinreichend komplexen Beispiels, nämlich eines simplen E-Mail-Clients. Dieser soll der Gesamtanwendung ermöglichen, E-Mails zu verschicken. Es wurde festgelegt, dass zur Realisierung die externe Bibliothek Java Mail API verwendet werden soll. Grundlage der Codebeispiele ist das Open-Source-Projekt TP-CORE, das von GitHub [1] heruntergeladen werden kann.

Planspiele

Mit den bereits vorhandenen Informationen können wir auch schon beginnen, agil und testgetrieben zu entwickeln. Auf einem Blatt Papier lässt sich rasch notieren, wie die Grundfunktionen eines einfachen E-Mail-Clients aussehen könnten:

  • Verbinden mit einem SMPT-Server, um Mails zu verschicken

  • Erstellen (Komponieren) einer E-Mail mit Betreff, Absender, Inhalt und möglichen Anhängen

  • Einlesen des Empfängers bzw. der Empfänger

  • Mail für den Versand komplettieren

Die Funktionalität lässt sich natürlich noch beliebig erweitern und gibt einen Vorgeschmack auf die Flexibilität, mit der wir ans Werk gehen. Basierend auf dem Java Mail API können wir mit den bereits aufgeschriebenen Erkenntnissen ein einfaches Interface definieren, das auch direkt implementiert wird. Um die nächsten Schritte durchführen zu können, sind allerdings einige Randbedingungen zu erfüllen. Dazu gehört der sichere Umgang mit einem Build-Werkzeug, das in unserem Fall Maven sein soll. Die wichtigsten Abhängigkeiten zu den Testframeworks aus Listing 1 sind:

  • JUnit 5 für Unit-Tests

  • JGiven für BDD-Testszenarios

  • BeanMatchers zum Testen der Konstruktoren etc.

Das führt uns direkt zum Erzeugen der der Implementierung zugehörigen Testfälle. Denn mit der Verwendung von Maven und dem Einbinden der Testframeworks als Abhängigkeit ist das Set-up des lokalen Arbeitsplatzes bereits abgeschlossen. Es gilt noch zu erwähnen, dass die Wahl der IDE grundsätzlich keine Rolle spielt, und sich die Vorliebe für NetBeans in diesem Workshop widerspiegelt.

Von Fall zu Fall

Gehen wir also davon aus, dass die Klasse MailClientImpl das zugehörige Interface MailClient implementiert. Sämtliche Testfälle MailClientImpl betreffend sind in der Testklasse MailClientImplTest zusammengefasst. Ziel ist es, möglichst alle Codezeilen durch entsprechende Testfälle abzudecken. Dabei sollen auch so viele Klassenmethoden wie möglich explizit durch die Testfälle aufgerufen werden.

Abbildung 1 zeigt die Auswertung aller Testfälle für MailClientImpl, bei der alle 22 Tests erfolgreich durchlaufen sind. In der Übersicht erkennt man auch sehr gut, wie die einzelnen Tests aufgebaut sind. Ebenso wie Klassenvariablen oder Methodennamen soll...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Gewinner-Teams

Wir bieten Lizenz-Lösungen für Teams jeder Größe: Finden Sie heraus, welche Lösung am besten zu Ihnen passt.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang