Schreibe niemals Unit Tests!

Keine Angst, ich mache nur Spaß. Schreib Unit-Tests! Immer! Für alles! Ausrufezeichen!

Hier könnte der Artikel schon zu Ende sein. Alles, was man wissen muss, ist: Tests sind gut. Teste unbedingt!

Leider gibt es da draußen viele Entwickler, die eine große Abneigung gegen Tests haben oder sie sogar hassen. Diese Einstellung beruht auf einer Reihe von Missverständnissen. Die populärsten davon dürften die Folgenden sein:

  • „Wir haben keine Zeit für Tests.“
  • „Ich weiß doch, dass mein Code funktioniert.“
  • „Ich hasse es, diese bescheuerten Tests zu pflegen.“

Dysfunktionale Teams und schlechte Entwickler-Angewohnheiten sind dermaßen weit verbreitet, dass viele Menschen tatsächlich davon ausgehen, Tests würden viel Zeit kosten, schwierig zu pflegen sein und nur das Offensichtliche zeigen. Dementsprechend werden sie als nutzlos, überflüssig, verzichtbar und nervig abgetan.
Ich habe lange in dieser “Testhölle” schmoren müssen, bis ich entschieden habe, dass sich daran etwas ändern muss. Am liebsten hätte ich alle Tests einfach verworfen. Schlechte Tests bringen keinerlei Mehrwert, behindern aber den Projektfortschritt. Von daher ist Löschen eine durchaus realistische Alternative. 
Besser ist es aber, dem Gedanken des Handwerks zu folgen und konsequent Qualität als Handlungsmaxime zu setzen. Tests sind ein Werkzeug, um qualitativ hochwertige Software zu schreiben. Qualitativ hochwertige Software spart erheblich Kosten bei Betrieb, Wartung und Weiterentwicklung. Aus genau diesem Grund sollten sorgfältig geschriebene Tests zur Denkweise eines jeden Entwicklers gehören und nicht, weil Blogs, Bücher oder Sonar es vorgeben.

Testgetriebene Entwicklung als Helfer in der Not

An dieser Stelle fragen sich viele: Wie können Tests das leisten? Meine Tests helfen mir dabei gar nicht. Testgetriebene Entwicklung (Test Driven Development - TDD) ist die Antwort. Im Internet findet man Unmengen an Informationen zu dieser Methode. Es gibt Verfechter und Gegner. Auf das Wesentliche reduziert, funktioniert TDD so: 

  • Schreibe einen fehlschlagenden Test, der genau eine einzige Sache testet (RED)
  • Schreibe genau so viel Geschäftslogik, um den Test zu bestehen (GREEN)
  • Refaktoriere den Code, um ihn aufzuräumen (REFACTOR)
  • Wiederhole diese Schritte, bis du fertig bist

Unit Tests – Refactor Kreislauf 

Damit dieser Kreislauf aber tatsächlich Sinn macht, müssen die Tests einigen Regeln entsprechend – leicht zu merken mit dem Akronym FIRST:

  • Fast (schnell)
  • Independent / Isolated (unabhängig)
  • Repeatable (wiederholbar)
  • Self Verifying (sich selbst verifizierend)
  • Timely  („rechtzeitig“)

Mit diesen Regeln im Hinterkopf kann man jetzt einhergehen und “Argumente” gegen Tests entkräften.

Keine Zeit zum Testen

Da Testen jetzt ein fester Bestandteil eines jeden Entwicklungsschrittes ist, kann gar nicht „keine Zeit dafür“ sein. Zu sagen: „Wir haben keine Zeit, zu testen“ ist wie zu sagen „Wir haben keine Zeit, zu entwickeln“ –  und mal ehrlich, aus diesem Blickwinkel betrachtet, zeigt sich schnell das eigentliche Problem.
Gute Tests können gar keine Zeit rauben – sie können die Entwicklung sogar beschleunigen, denn: 

  • Schnelle Test sind… nun ja, schnell.
  • Fehler fallen früher auf.
  • Man weiß, wann man fertig ist: Keine goldenen Türklinken, kein Over-Engineering.
  • Mit FIRST entwickelte Tests sind leicht zu pflegen. Das spart Zeit.

Ich weiß doch, dass mein Code funktioniert

Das mag sogar stimmen. Zumindest wenn der Code gerade frisch geschrieben wurde. Aber was, wenn der Code refaktoriert worden ist? Wie weiß man dann, dass er immer noch funktioniert? Was ist mit nächster Woche? Nicht immer kann man sich daran erinnern, was der Code genau macht und warum. Was ist mit den Kollegen? Woher sollen die das wissen?

Tatsächlich testen Tests nicht, ob der Code etwas tut, sondern sie spezifizieren, was er tun soll. Jetzt und in Zukunft. Man ändert Tests nur, wenn sich die Spezifikation geändert hat. Dadurch wird der Test fehlschlagen und das wiederum ist der einzige Grund, warum man funktionale Änderungen am Produktivcode vornimmt. 

Wenn man nicht den Test zuerst schreibt, woher weiß man dann, was sich ändern muss und wo? Woher weiß man, dass die Änderung den gewünschten Effekt hat? Woher wissen es später die Kollegen? 

Ich hasse es, diese bescheuerten Tests zu pflegen

Was das angeht, weiß ich genau, worum es geht. Wir alle haben schon so gedacht. Wir kennen alle diese “Was zur Hölle haben die sich denn dabei gedacht?” Momente, wenn man die Tests anderer Leute wartet. Gründe dafür können sein:

  • Man testet Code, der nicht testfreundlich entwickelt wurde.
    • Der Testaufbau ist entsprechend umfangreich, kompliziert und brüchig – die Ausführung ist undurchsichtig.
  • Testcode ist kein Produktivcode und muss demzufolge auch nicht die gleichen Qualitätsvorgaben erfüllen
    • Aufgrund von irreführenden Namen, Aufbau und Redundanzen, ist der Test schwierig zu lesen und zu verstehen.

Testgetrieben entwickelter Code macht keinen Unterschied zwischen Geschäftslogik und Tests. Für jede Zeile Code gelten die gleichen Regeln – und natürlich ist Test-Code Bestandteil von Refaktorierung. 
Die Tests zuerst zu schreiben hilft dabei, genau das angemessene Design zu finden. Code wird nur geschrieben, um einen bestehenden Test zu erfüllen – das macht ihn automatisch testfreundlich.

Man glaubt nur, was man sieht

Leider hat aber eben alles auch seinen Preis und das bedeutet in diesem Fall: Um wirklich von TDD profitieren zu können, musst man sich die Hände schmutzig machen:

  • Recherche und Lektüre sind Pflicht.
  • Training mit Anderen in Coding Dojos oder auf eigene Faust mit Code Katas.

Zugegeben: Anfangs war ich selbst sehr skeptisch, was TDD betraf. Der Wendepunkt kam für mich, als ich mit dem WordWrap-Kata übte. Ich kam schneller als gedacht zu einer sehr einfachen Lösung, viel einfacher, als es „meine“ Lösung gewesen wäre, wenn ich nicht TDD angewandt hätte. Ich bemerkte, wie hinderlich meine bisherigen Testing-Angewohnheiten gewesen waren und wie schlecht sich das auf meine Geschäftslogik ausgewirkt hatte. 

itemis hilft

Als agiles Unternehmen bieten wir natürlich Coding Dojos und TDD-Workshops an. Ich hatte die Möglichkeit, an einem dieser Workshops teilzunehmen und kann sagen: Es war die Mühen wirklich wert. Der Workshop war anstrengend, hat sich aber absolut gelohnt. Mein Dank geht besonders an meinen Kollegen Christian Fischer, der ein sehr leidenschaftlicher und kompetenter Workshop-Leiter ist.
Das Training geht über drei Tage und beinhaltet jede Menge praktischer Übungen. Am Ende kann man optional an der Abschlussprüfung teilnehmen. Besteht man diese, erhält man das iSQI Test Driven Development-Zertifikat.

Also: Wie wäre es, aus der Testhölle zu entkommen? Melde dich einfach bei uns. Wir würden uns freuen, von dir zu hören! 

Hier klicken und  Kontakt aufnehmen

Über Jan Mosig

Jan Mosig arbeitet für die itemis AG am Standort Leipzig. Er beschäftigt sich mit Problemen im Projektalltag und setzt zu deren Lösung auf technische Softwarequalität, Agile und Mut zur Veränderung.