4.3.2006
* frei nach der Film-Noir-Parodie "Tote tragen keine Karos" von Carl Reiner
von Frank Westphal und Johannes Link
erschienen im Java Magazin 3/2006
Johannes und ich haben für seine “Jenseits des Tellerrands” Kolumne im Java Magazin ein kleines literarisches Experiment gewagt.
Wir beuten das Erbe von Raymond Chandler aus, um zu zeigen, wie sich Benutzergeschichten und andere Anforderungen in einer für Kunden wie Entwickler gleichermaßen verständlichen Sprache kommunizieren, am konkreten Beispiel dokumentieren und zur Abnahme automatisiert testen lassen.
Verwendung findet dabei FIT, ein kleines agiles Akzeptanz- und Systemtest-Framework.
Der Besuch
Es dröhnte und pochte in meinen Ohren.
Das Dröhnen kam von innen und war vermutlich auf die Flasche billigen Brandys zurückzuführen, die mir mein letzter Kunde, ein heruntergekommener Bänker, anstatt der versprochenen 100 Euro als Bezahlung angeboten hatte.
Privatentwickler zu sein ist nicht immer leicht.
Das Pochen jedoch kam von meiner Tür und wollte nicht aufhören.
Ich erinnerte mich dunkel an eine via Skype getroffene Verabredung und schleppte mich vom Bett zum Schreibtischstuhl im Nebenzimmer, meine Klamotten hatte ich glücklicherweise noch an, und rief dem Türklopfer ein gequältes “Rein mit Ihnen!” entgegen.
Erwartet hatte ich eine Frau mittleren Alters, doch herein trat eine Blondine, etwa um die dreißig und mit ausreichend Bein ausgestattet, um mir schwindelig werden zu lassen – wäre ich es nicht sowieso schon gewesen.
“Mr. Softlowe?”
“Korrekt. Philip Softlowe. Das bin ich.”
“Gestatten, Mrs. Customley.
Wir haben geskypt.
Ich dachte schon, Sie wollten mir gar nicht mehr öffnen.”
“Ich bin so früh am Tag noch etwas … schüchtern.”
Meine Gesichtsmuskelatur brach in ein anrüchiges Grinsen aus.
Um es kurz zu machen, nach einigem freundlichen Geplänkel rückte sie mit ihrem Anliegen heraus:
Sie wollte “Unregelmäßigkeiten” in den Kontoauszügen ihres Mannes überprüfen lassen.
In anderen Worten, ich sollte ihr ein kleines Programm schreiben, das aus allen Kontobewegungen ihres Mannes die verdächtigen Positionen herausfiltern und für spätere “Referenz” protokollieren sollte.
Ich zögerte.
Nicht dass ich nach all den Jahren in den Gossen der Softwareentwicklung noch Skrupel hätte, aber ein bisschen überrascht war ich dennoch.
Sollte ein Mann eine solche Frau für eine andere vernachlässigen?
Der Fall roch irgendwie faul.
Doch ich verwarf alle Einwände meiner inneren Stimme; die Miete war fällig und der letzte Cash-zahlende Kunde lag schon ein paar Wochen zurück.
“Ich bekomme 200 am Tag.
Plus Spesen.
Und 30 Cent für jeden Kilometer in meiner Kiste.”
“Das sollte ja dann für eine Woche reichen.”
Sie blätterte zwei 500-Euro-Scheine auf den Tisch.
“Und hier die Auszüge meines Mannes vom letzten Monat.
Die verdächtigen Positionen habe ich gelb markiert.”
Ein dickes Bündel Ausdrucke nahm den Weg aus ihrer Handtasche auf meinen Schreibtisch.
Ein einzelnes Blatt sah in etwa so aus:
Dabei war der zweite Eintrag mit einem gelben Markerstift eingefärbt worden.
Ich ließ meinen Daumen durch das Bündel fahren.
Es waren mindestens 200 Blätter.
Ihr Mann schien den ganzen Tag nichts anderes zu tun, als Überweisungen zu schreiben und Kreditkartenbelege zu quittieren.
“Nicht so schnell, Herzchen”, grinste ich sie an und versuchte dabei, meine Kopfschmerzen zu ignorieren, “Was bedeutet denn ‘verdächtig’?”
“Ganz einfach”, flötete sie und schaute mir tief in die Augen.
“Verdächtig sind alle Ausgaben zwischen 100 und 500 Euro, die im Verwendungszweck nicht ‘Rate’, ‘Miete’ oder ‘Strom’ haben.
Und natürlich nur an Tagen, an denen mein werter Gatte auf Geschäftsreise war.”
Als hätte sie meinen nächsten Einwand vorhergesehen, zog sie eine Liste mit den bisherigen und auch künftigen Geschäftsreisen ihres Mannes aus der Tasche, und warf sie mit einem Schwung über den Schreibtisch in meinen Schoß.
“Sind sie privat auch so ruppig, Süße?”, entgegnete ich mit meinem anzüglichen Grinsen.
“Ihr Ton gefällt mir nicht, Mr. Softlowe.”
“Macht nichts, ich will ihn nicht verkaufen.”
“Guten Tag, Mr. Softlowe.”
Ohne weiteren Blickkontakt schritt sie aus meinem Büro und warf die Tür hinter sich zu.
Die Lady gefiel mir.
Nicht nur wegen ihrer äußeren Reize, ihr zielstrebiges Handeln imponierte mir fast ebenso.
Wie viele meiner Aufträge hatten mir wochenlang nichts als detektivischen Spürsinn abverlangt: Unklare Rollenverhältnisse, veränderte Anforderungen und übelste Widersacher waren an der Tagesordnung.
Hier war endlich eine Kundin, die wusste, was sie wollte, und nicht in prosaischen Rätseln sprach.
Die gelieferten Beispieldaten sollten meine Entwicklung auf eine erste erfolgreiche Fährte setzen.
Bei dieser Frau durften mir keine Fehler passieren …
Erster Anlauf
Um möglichst bald wieder Grund für einen Skype-Ruf zu haben, machte ich mich gleich an die Arbeit.
Das heißt, nachdem ich meinem Kopf eine Abkühlung unter der Dusche gegönnt und meinem Hirn eine Tasse starken Java gemacht hatte.
Mein Leitspruch war: Nicht Fehler töten Projekte, fehlende Tests tun es.
Und seit der Verschärfung des Haftungsgesetzes für Privatentwicklungen sicherte ich jeden Kundenwunsch durch automatisierte Akzeptanztests ab; das hatte mir schon einigen Ärger mit der Europäischen Projektpolizei erspart.
Für einen LBD (Low Budget Developer) wie mich gab es in diesen Zeiten nur ein Testwerkzeug, das ich mir leisten konnte und das eine offizielle Zulassung der Europäischen Softwarekommision besaß: FIT.
Was ist FIT?
Was JUnit für Unit Tests ist, ist FIT (Framework for Integrated Test) für System- und Akzeptanztests.
Kundenanforderungen werden nebst Szenarien und Testdaten in Word, Excel oder Wiki dokumentiert und, im HTML-Format gespeichert, von FIT verarbeitet.
Das Open-Source-Framework liest diese Dokumente ein, interpretiert die darin eingebetteten Tabellen als auszuführende Testfälle und schreibt sein Testergebnis direkt in die entsprechenden Tabellenzellen (je nach Resultat in roter oder grüner Farbe) zurück.
Die Übersetzung der Wünsche meiner intriganten Schönheit in entsprechende FIT-Tabellen war das reinste Kinderspiel.
Die Kontoauszüge entschlackte ich um Überflüssiges und ergänzte den Verdächtig-Aspekt:
Wie benutzt man FIT?
Mit FIT können wir im Projektverlauf ein ausführbares Anforderungsdokument erstellen, das die umgangssprachlichen Anforderungen des Kunden in konkrete Akzeptanzkriterien überführt und jederzeit auf Knopfdruck überprüft.
Auf diese Weise schließt FIT nicht nur eine wichtige Kommunikationslücke zwischen den Domänenexperten und uns Softwareentwicklern, sondern beantwortet gleichzeitig die wichtige Frage, wann die von uns gelieferte Software eigentlich fertig ist.
Hinter jede HTML-Tabelle stecken wir eine kleine Adapterklasse – eine so genannte Fixture –, welche die Testdaten zu interpretieren weiß und die Verbindung zur zu testenden Anwendung herstellt.
Als Beispiel hier der Kontoauszug:
public class Kontoauszug extends fit.ColumnFixture {
public Date Datum;
public Euro Betrag;
public String Empfänger;
public String Verwendungszweck;
public boolean Verdächtig() {
return new Kontobewegung(Datum, Betrag, Empfänger,
Verwendungszweck).verdächtig();
}
}
Die aufgedruckten Smartchips erlaubten es mir, die Auszüge in wenigen Minuten elektronisch zu erfassen.
Lediglich die verdächtigen Positionen musste ich per Hand nachtragen.
Auch die Dienstreisen waren in kürzester Zeit umgesetzt:
Programmiert hatte ich diese kleine Aufgabe schon am Abend, alle Positionen wurden korrekt klassifiziert und ich erwartete, die zufriedene Kundin am nächsten Abend in meinem Büro, um sie – nach Klärung des geschäftlichen Erfolgs – auch von meinen privaten Vorzügen überzeugen zu können.
Neue Wünsche
Ich hatte mich gerade rasiert und meine Tastaur von den Fingerabdrücken und Schokoflecken der vergangenen Jahre befreit, als La Cliente Fatale eintrat – diesmal ohne anzuklopfen.
“Haben wir uns nicht schon mal irgendwo gesehen?”, fragte ich, um die Stimmung zu heben, in gewohnt lockerem Ton.
“Könnte sein, ich war schon mal irgendwo.”, kam prompt als Antwort.
“Sie sind ja sehr geschickt mit Ihren Fingern.”, zeigte sie sich vom sichtbaren Projektfortschritt – alle Testfälle waren grün kariert – beeindruckt.
Nicht beeindruckt genug jedoch, um nicht gleich noch nachzulegen …
“Nun, Mr. Superlowe, ich habe da noch eine kleine Zusatzaufgabe”, flüsterte sie und kam dabei mit ihrem Mund kurzzeitig dem meinen verdächtig nahe.
“Jetzt wüsste ich gerne, wann und wo mein treuer Mann die nächste ‘Zusatzausgabe’ plant.
Da lässt sich doch sicherlich ein Muster erkennen, oder?”
Mein ratloser Blick schien sie nicht zu verunsichern, aber die erotisierte Stimmung löste sich in ihrem gereizten Ausruf auf:
“Wofür bezahle ich Sie eigentlich, Sie Schmierenprogrammierer!
In drei Tagen erwarte ich von Ihnen Ort und Zeit der nächsten zu erwartenden ‘Sonderausgabe’ meines Mannes.”
Auch diesmal verließ sie meine bescheidenen Räumlichkeiten, ohne einen Blick zurückzuwerfen.
“So long, Zuckerpuppe!”
Die Lady gefiel mir immer besser.
Zweiter Durchlauf
Den ursprünglichen Zettel mit den Dienstreisen fand ich im Müll – leider ein wenig verschmutzt von den Resten der 13 Pizzaschachteln, die ich danach in die Tonne gestopft hatte.
Zu entziffern waren trotzdem noch die Städte, in die der Angetraute meiner Klientin seine Reisen getätigt hatte bzw. tätigen würde:
Ich erspare Ihnen die Details der beiden schlaflosen, whiskeygetränkten und zigarillorauchgeschwängerten Nächte, in denen ich versuchte, das System hinter seinen Dienstreisen und Vergnügungsausgaben zu erkennen.
Doch irgendwann war ich überzeugt, die Formel – ähnlich komplex wie die Lösung von Differenzialgleichungen höherer Ordnung – gefunden zu haben, und FIT warf mir die folgende Ergebnistabelle aus:
Sonderfälle
Hm, der Neujahrstag und Dienstreise?
Sollte ich einen Fehler begangen haben?
Sofort schickte ich eine Skype-Nachricht an Mrs. Customley, ob sie sich vorstellen könne, dass ihr Mann am Neujahrstag …
Die Antwort kam prompt: “Dienstreisen an Feiertagen sagt mein Mann immer kurzfristig ab und bleibt zu Hause.”
Sehr interessant – da gab es also offensichtlich ein paar Sonderfälle, die mir bei der Anforderungsanalyse durch die Lappen gegangen waren.
Jetzt nicht mehr:
Und nach Ausfilterung der Feiertage spuckte mein Programm nun plötzlich ein anderes, völlig plausibles Ergebnis aus:
Hatte ich diesmal auf mehr Zuwendung durch Mrs. Geheimnisvoll gehofft, so wurde ich gründlichst enttäuscht.
Reserviert und zugeknöpft nahm sie in meinem Büro den Memory-Stick mit Programm, Daten und Auswertung entgegen und war verschwunden, noch ehe ich zu einem gewohnt lässigen “Hätten Sie nicht Lust …” ansetzen konnte.
Sie war schwerer zu knacken, als ich dachte.
Post Mortem
Drei Tage vergingen, ohne dass ich von ihr hörte.
Dass sie mich so lange zappeln ließ, hatte mich zermürbt und ich war innerlich bereit, für sie ein Eine-Frau-Mann zu werden.
Mit vorbereiteter Ausrede klickte ich ihren Skype-Anschluss an.
‘This account has been deleted’ war die Antwort und ich blieb verstört und ahnungslos, mit der zweiten Flasche Brandy als einzigem Freund, zurück.
‘Ahnungslos’ aber nur so lange, bis ich am Morgen des 24. Februars folgende Meldung in meinen personalisierten Google-News fand:
Stuttgart.
Am gestrigen Abend wurde Europaminister Wackelstein von seiner Frau im Restaurant Tanzbein erschossen.
Seine Frau wurde noch am Tatort von den anwesenden Leibwächtern überwältigt und gab später zu Protokoll, sie habe ihren Mann aus Eifersucht getötet.
Tatsächlich saß am Tisch des Ministers die 65-jährige berühmte Tänzerin Angelique Leichtfuß, bei welcher der Minister seit einigen Monaten regelmäßig Tanzunterricht nahm, um für den Gala-Empfang anlässlich seines fünften Hochzeitstags im März gerüstet zu sein.
Der zuständige Polizeichef sagte …
Ich schaltete den Monitor aus, lehnte mich im Sessel zurück und zündete mir eine Zigarette an.
Die Kopfschmerzen waren größer denn je und ich spielte mit dem Gedanken, meine Lizenz als Privatentwickler endgültig an den Nagel zu hängen.
Links/Literaturverweise
17.11.2005
Frank Westphal
Testgetriebene Entwicklung
mit JUnit & FIT:
Wie Software änderbar bleibt
dpunkt.verlag
346 Seiten
November 2005
ISBN 3-89864-220-8
Bei Amazon ansehen
Beschreibung
Testgetriebene Entwicklung geht von einem fehlschlagenden Test aus.
Software wird in kleinen sicheren Schritten entwickelt, die abwechselnd darauf abzielen, eine neue Anforderung zu implementieren (den fehlschlagenden Test also zu erfüllen) und das Design zu verbessern (und dabei weiterhin alle Tests zu bestehen).
-
Wenn frühes und häufiges Testen wichtig ist, warum schreiben wir nicht für jedes neue Feature zuerst einen automatisierten Test?
So können wir während der Entwicklung jederzeit unsere Tests ausführen und lernen, ob unser Code wie gewünscht funktioniert.
-
Wenn Design wichtig ist, warum investieren wir dann nicht Tag für Tag darin?
So können wir dafür sorgen, dass es möglichst einfach bleibt und nicht mit der Zeit zunehmend degeneriert.
-
Wenn Anforderungsdefinition wichtig ist, warum ermöglichen wir unseren Kunden dann nicht, in einem ausführbaren Anforderungsdokument Testfälle für konkrete Anwendungsbeispiele zu spezifizieren?
So können wir dokumentieren, welche Funktionalität tatsächlich gefordert ist, und anschließend verifizieren, ob die Erwartungen des Kunden erfüllt werden.
Das Buch führt mit praktischen Beispielen in die Testgetriebene Entwicklung mit den Open-Source-Werkzeugen JUnit und FIT ein.
Frank Westphal has turned his extensive experience in using and teaching developer testing with JUnit and FIT into a thorough and usable guide for programmers and testers, including the first published guide to JUnit 4.
What I was most struck by in reading this book was the combination of philosophical background and detailed, practical advice.
– Kent Beck, Three Rivers Institute
Amazon-Rezensionen
ganz aus dem häuschen
– Thomas Steinbach
Warum sind wir darauf nicht schon eher gekommen?
– H. Mausolf
Grandios !!
– Bernd Will
Lockere Lektüre für flotte Erfolge
– Gernot Starke
Motivation für die Praxis
– Frankmartin Wiethüchter
Seit langem kein Buch mehr so schnell durchgearbeitet!
– Ulrich Storck
Rundum gelungen
– Jens Uwe Pipka
Übers Entwickeln und Entwerfen - auf testgetriebene Art
– Christoph Steindl
Ideal für professionelle Softwareentwickler
– Dierk König
Testen als Mittel zum Zweck
– Stefan Roock
Buchbesprechungen
Inhaltsverzeichnis
- Was ist Testgetriebene Entwicklung?
- Warum Testgetriebene Entwicklung?
- Über dieses Buch
- Merci beaucoup
Kapitel 2: Testgetriebene Entwicklung, über die Schulter geschaut
- Eine Programmierepisode
- Testgetriebenes Programmieren
- Möglichst einfaches Design
- Ein wenig Testen, ein wenig Programmieren ...
- Evolutionäres Design
- Natürlicher Abschluss einer Programmierepisode
- Refactoring
- Abschließende Reflexion
- Häufige Integration
- Rückblende
- "Aus dem Bauch" von Sabine Embacher
- Download und Installation
- Ein erstes Beispiel
- Anatomie eines Testfalls
- Test-First
- JUnit in Eclipse
- Das JUnit-Framework von innen
- »Assert«
- »AssertionFailedError«
- »TestCase«
- Lebenszyklus eines Testfalls
- »TestSuite«
- »TestRunner«
- Zwei Methoden, die das Testen vereinfachen
- Testen von Exceptions
- Unerwartete Exceptions
- "Woran erkennt man, dass etwas testgetrieben entwickelt wurde?" von Johannes Link
- JUnit 4
Kapitel 4: Testgetriebene Programmierung
- Die erste Direktive
- Der Testgetriebene Entwicklungszyklus
- Die Programmierzüge
- Beginn einer Testepisode
- Ein einfacher Testplan
- Erst ein neuer Test ...
- ... dann den Test fehlschlagen sehen
- ... schließlich den Test erfüllen
- Zusammenspiel von Test- und Programmcode
- Ausnahmebehandlung
- Ein unerwarteter Erfolg
- Ein unerwarteter Fehlschlag
- "Rückschritt für den Fortschritt" von Tammo Freese
- Vorprogrammierte Schwierigkeiten
- "Zwei offene Tests sind einer zu viel" von Tammo Freese
- Kleine Schritte gehen
- "Halten Sie Ihre Füße trocken" von Michael Feathers
Kapitel 5: Refactoring
- Die zweite Direktive
- Die Refactoringzüge
- Von übel riechendem Code ...
- ... über den Refactoringkatalog
- ... zur Einfachen Form
- Überlegungen zur Refactoringroute
- Substitution einer Implementierung
- Evolution einer Schnittstelle
- "Coding Standards bewusst verletzen" von Tammo Freese
- Teilen von Klassen
- Verschieben von Tests
- Abstraktion statt Duplikation
- Die letzte Durchsicht
- Ist Design tot?
- "Durch zerbrochene Fenster dringen Gerüche ein" von Dave Thomas & Andy Hunt
- Richtungswechsel ...
- ... und der wegweisende Test
- Fake it ('til you make it)
- Vom Bekannten zum Unbekannten
- Retrospektive
- Tour de Design évolutionnaire
- Durchbrüche erleben
Kapitel 6: Häufige Integration
- Die dritte Direktive
- Die Integrationszüge
- Änderungen mehrmals täglich zusammenführen ...
- "Taxi implements Throwable" von Olaf Kock
- ... das System von Grund auf neu bauen
- ... und ausliefern
- Versionsverwaltung (mit CVS oder Subversion)
- Build-Skript mit Ant
- Build-Prozess-Tuning
- Integrationsserver mit CruiseControl
- Aufbau einer Staging-Umgebung
- Teamübergreifende Integration
- Gesund bleiben
- "Eine Geschichte über die Häufige Integration" von Lasse Koskela
Kapitel 7: Testfälle schreiben, von A bis Z
- Aufbau von Testfällen
- Benennung von Testfällen
- Buchführung auf dem Notizblock
- Der erste Testfall
- Der nächste Testfall
- Erinnerungstests
- Ergebnisse im Test festschreiben, nicht berechnen
- Erst die Zusicherung schreiben
- Features testen, nicht Methoden
- Finden von Testfällen
- Generierung von Testdaten
- Implementierungsunabhängige Tests
- Kostspielige Setups
- Lange Assert-Ketten oder mehrere Testfälle?
- Lerntests
- Minimale Fixture!
- "Einfache Tests - einfaches Design" von Dierk König
- Negativtests
- Organisation von Testfällen
- Orthogonale Testfälle
- Parameterisierbare Testfälle
- Qualität der Testsuite
- Refactoring von Testcode
- Reihenfolgeunabhängigkeit der Tests
- Selbsterklärende Testfälle
- String-Parameter von Zusicherungen
- Szenarientests
- Testexemplare
- Testsprachen
- Umgang mit Defekten
- "Eine Frage der (Test-)Kultur" von Christian Junghans & Olaf Kock
- Umgang mit externem Code
- Was wird getestet? Was nicht?
- Zufälle und Zeitabhängigkeiten
- "Der zeitlose Weg des Testens" von Lasse Koskela
Kapitel 8: Isoliertes Testen, durch Stubs und Mocks
- Verflixte Abhängigkeiten!
- Was ist die Unit im Unit Test?
- Mikrointegrationstest versus strikter Unit Test
- Vertrauenswürdige Komponenten
- "Vertrauen - und Tests" von Bastiaan Harmsen
- Austauschbarkeit von Objekten
- Stub-Objekte
- Größere Unabhängigkeit
- Testen durch Indirektion
- Stub-Variationen
- Testen von Mittelsmännern
- Self-Shunt
- Testen von innen
- Möglichst frühzeitiger Fehlschlag
- Erwartungen entwickeln
- Gebrauchsfertige Erwartungsklassen
- Testen von Protokollen
- Mock-Objekte
- Wann verwende ich welches Testmuster?
- "Wo Mock-Objekte herkommen" von Tim Mackinnon & Ivan Moore & Steve Freeman
- Crashtest-Dummies
- Dynamische Mocks mit EasyMock
- Stubs via Record/Replay
- Überspezifizierte Tests
- Überstrapazierte Mocks
- Systemgrenzen im Test
- "Mock-Objekte machen glücklich" von Moritz Petersen
Kapitel 9: Entwicklung mit Mock-Objekten
- Tell, don't ask
- Von außen nach innen
- Wer verifiziert wen?
- Schnittstellen finden auf natürlichem Weg
- Komponierte Methoden
- Vom Mock lernen für die Implementierung
- Viele schmale Schnittstellen
- Kleine fokussierte Klassen
- Tell und Ask unterscheiden
- nereimmargorP sträwkcüR
- Schüchterner Code und das Gesetz von Demeter
- Fassaden und Mediatoren als Abstraktionsebene
- Rekonstruktion
- "Meister, ..." von Dierk König
Kapitel 10: Akzeptanztests mit FIT (Framework for Integrated Test)
- Von einer ausführbaren Spezifikation ...
- Download Now
- Schritt für Schritt für Schritt
- ... zum ausführbaren Anforderungsdokument
- Die drei Basis-Fixtures
- »ActionFixture«
- Richtung peilen, Fortschritt erzielen
- Fixture wachsen lassen, dann Struktur extrahieren
- Nichts als Fassade
- Die Fixture als zusätzlicher Klient
- Aktion: Neue Aktion
- »ColumnFixture«
- Fixture-Interkommunikation
- Negativbeispiele
- Transformation: Action -> Column
- »RowFixture«
- Einfacher Schlüssel
- Mehrfacher Schlüssel
- Abfragemethoden einspannen
- »Summary«
- "Warum drei Arten von Fixtures?" von Ward Cunningham
- »ExampleTests«
- »AllFiles«
- Setup- und Teardown-Fixtures
- Das FIT-Framework von innen
- »FileRunner«
- »Parse«
- »Fixture«
- Annotationsmöglichkeiten in Dokumenten
- »TypeAdapter«
- »ScientificDouble«
- Domänenspezifische Grammatiken
- »ArrayAdapter«
- »PrimitiveFixture«
- Domänenspezifische Fixtures
- Anschluss finden
- Stichproben reiner Geschäftslogik
- Integrationstests gegen Fassaden und Services
- "Survival of the FIT Test" von Steffen Künzel & Tammo Freese
- Oberflächentests
- Kundenfreundliche Namen
- FitNesse
- FitLibrary
- Akzeptanztesten aus Projektsicht
Kapitel 11: Änderbare Software
- "Harte Prozesse führen zu harten Produkten" von Dierk König
- Konstantes Entwicklungstempo
- "Alten Code testgetrieben weiterentwickeln" von Juan Altmayer Pizzorno & Robert Wenner
- "Die Latte liegt jetzt höher" von Michael Feathers
- Kurze Zykluszeiten
- Neue Geschäftsmodelle
- "Bug-Trap-Linien" von Michael Hill
Behandelte Werkzeuge
Quellcode
Die Beispiele aus den Kapiteln 2,
3,
4,
5,
6,
7,
8 können Sie sich auch hier herunterladen.
29.4.2005
von Frank Westphal und Johannes Link
erschienen im OBJEKTspektrum 3/2005
"From Stoplight to Spotlight": Vormals zu einer Phase im Entwicklungsprozess erklärt und oft genug als Schlusslicht des Projekts betrachtet, spielt sich das Testen heute als Aktivität ab und geht bei testgetriebener Entwicklung sogar allem anderen mit rotgrünem Scheinwerferlicht voraus.
In der Softwarebranche breitet sich eine Kluft aus. Auf der einen Seite sehen wir Entwicklerteams, die ihre Software schnell und zuverlässig ändern können. Sie schreiben automatisierte Testfälle für alles, was womöglich schief gehen könnte, und halten ihren Code durch ständiges Refactoring sauber und flexibel. Auf der anderen Seite sehen wir Teams, deren Entwicklungsgeschwindigkeit mit fortschreitender Projektdauer immer weiter sinkt. Sie testen ihr System überwiegend manuell und ihr Code von gestern steht den Anforderungen von heute nicht selten im Weg. Während erstere ihren Kunden dabei helfen, neue Geschäftsideen möglichst schnell in hoher Qualität umzusetzen, stehen letztere unter einem immer höheren Druck und der Drohung, durch "billige" Teams in Offshoring-Ländern ersetzt zu werden.
Entwickler, die das Testen lieben gelernt haben?
Eingeläutet wurde der Wandel beim Testen vor nunmehr sieben Jahren durch Extreme Programming (XP) und JUnit. Testen war auf einmal cool. JUnits grüner Balken machte süchtig, sorgte er doch für ein lang vermisstes Gefühl: das Vertrauen, dass die produzierte Software tatsächlich wie gewünscht funktionierte. Doch schnellen Testerfolgen folgte erste Ernüchterung. Bestimmte Ecken ließen sich nicht so einfach automatisiert testen, so z. B. grafische Benutzungsschnittstellen, Enterprise Java Beans (EJBs), Datenbanken, Threads und Legacy Code. Hier zeigte sich dann auch, wer wirklich testgetrieben entwickelte und wer nicht. Denn Testprobleme weisen zumeist auf eine Design- oder Prozessschwäche hin.
Heute gelten diese Herausforderungen als gemeistert. Was sich programmieren lässt, lässt sich auch testen. Der Weg zu dieser Erkenntnis führt über einige Hürden; erfolgreiches Testen verlangt eben mehr als die bloße Beherrschung des Test-Frameworks. Insbesondere zeigt sich meist recht schnell, dass zeitlich nachgeordnetes Testen wesentlich ineffektiver ist als das Schreiben der Tests vor der Implementierung: Zum einen lässt sich Testbarkeit im Nachhinein nur mit Mühe erzwingen, zum anderen können vorab geschriebene Tests das Design lenken. Gerade dieser Vorteil testgetriebener Entwicklung ist jedoch – auch in Projekten mit hoher Testkultur – in vielen Köpfen noch nicht gefestigt.
Wohin geht die testgetriebene Entwicklung?
Nachdem sich die meisten Projekte bisher nur auf Unit-Tests gestützt haben, entdecken viele den Nutzen von System- und Akzeptanztests. Wenn diese Tests aus der Feder des Kunden bzw. der Fachabteilung kommen, kann so eine wichtige Kommunikationslücke zwischen den Domänenexperten, die die Anforderungen kennen, und den Entwicklern, die diese realisieren, geschlossen werden. Hat sich JUnit als De-facto-Standard für Entwicklertests etabliert, so schickt sich derzeit Ward Cunninghams Framework for Integrated Test (FIT) an, das kundenfreundlichste Akzeptanztest-Framework zu werden. Der angezeigte Trend geht hier eindeutig in Richtung des ausführbaren Anforderungsdokuments. Man verbindet effektiv die Anforderung mit ihrem Abnahmetest. Geht die Formulierung dieser Tests der eigentlichen Entwicklung voraus, so besteht durchaus die Möglichkeit, das traditionelle Anforderungsmanagement auf den Kopf zu stellen. Dabei verändert sich die Rolle des Testers. Anstatt den Entwicklern wegen tausender Kleinigkeiten auf die Finger zu klopfen, kann er nun mit dem Kunden dessen Anforderungen in testbare und eindeutige Beispiele überführen. Auch auf das Projektmanagement wirken sich die feature-basierten Akzeptanztests positiv aus, stellt diese Testart doch ein untrügliches Mittel dar, um den tatsächlichen Projektfortschritt messen und damit "managen" zu können.
Wie gut ein Prozess wirklich "sitzt", zeigt sich, wenn der Stresspegel zunimmt. Noch sehen wir häufig, dass Tests weggelassen werden, wenn die Zeit knapp wird. Nur wer seine Reflexe soweit verändert hat, dass er trotz Zeitdruck weiterhin an seinen guten Gewohnheiten festhält, hat sich überzeugt: Testen spart Zeit und Geld. Zum einen führen intensive Unit-Tests zu deutlich reduzierten Fehlerraten. Von einigen XP-Teams wird mittlerweile berichtet, dass ihre Software praktisch fehlerfrei sei. So hätten die Anwender, nachdem sich die Software länger als ein Jahr in Produktion befände, noch keinerlei Fehler entdeckt. Zum anderen ermöglichen erst automatisierte Tests eine schnelle, evolutionäre Anpassung des Designs an neue Anforderungen. Die Testautomatisierung erweist sich damit als eine Kosten sparende und Effizienz steigernde Maßnahme, sobald die initiale Lernkurve überwunden ist. Wie nicht zuletzt durch Toyota im Automobilbau demonstriert: Produktivität und Qualität sind keine widersprüchlichen Ziele.
Die Grundannahme, dass Software nun mal "buggy" ist, wird sich sicher noch eine Zeit lang halten, jedoch mehr und mehr entkräftet werden. Wer effektiv testet, wird seine Software jederzeit ausliefern können, ohne dass die Qualität einknickt. Die Zykluszeiten von einer neuen Anforderung zum produktiven Code werden zukünftig drastisch kürzer werden und dadurch neue Geschäftsmodelle ermöglichen. Entwickelt wird in Zukunft nur noch geschäftswertorientiert: Die Anforderung mit der größten Wertschöpfung kommt zuerst. Inkrementelle Entwicklung wird zum Synonym für inkrementelle Finanzierung. Möglich wird dieser Wandel unter anderem durch automatisierte Tests.