IS-Rating: Planungssicherheit durch transparente Qualität

Automatisierte Unit-Tests

Hierunter sind Tests aus Sicht und in der Verantwortung der Programmierer zu verstehen.

Zielsetzungen

  • Ausführbare Spezifikation und Dokumentation von Detailaufgaben (Was soll diese Methode/Funktion genau leisten?),
  • Regressionstests (erhöhen Entwicklerproduktivität, reduzieren Kollateralschäden, sichern Refaktorierung ab).
  • Testbarkeit des Quellkodes (erhöht Strukturierung, reduziert Kopplung),

Erläuterungen

Unit-Tests stellen eine detaillierte ausführbare Spezifikation der Aufgaben einer jeden Methode/Funktion in einer Software dar. Erfüllt eine Methode diese Spezifikation nicht, schlägt der Test fehl. Unit-Tests sind nicht Bestandteil des Produktivkodes sondern werden nur bei Entwicklung und Änderung zur Überprüfung von dessen Eigenschaften ausgeführt. Erfahrungsgemäß haben wirksame Unit-Tests ungefähr den gleichen Programmumfang wie der eigentliche Produktivkode.
Ihr Nutzen liegt primär bei den Entwicklern. Die Qualität der Unit-Tests bestimmt, wie schnell sich deren zusätzlicher Erstellungsaufwand für diese amortisiert.

Nutzen

Unit-Tests bilden als ausführbare Spezifikation einen wichtigen Teil der Dokumentation.
Außerdem ermöglichen sie als detaillierte Regressionstests erfahrungsgemäß eine deutliche Beschleunigung der Entwicklung des Produktivkodes. Sie können verhindern, dass bei Programmänderungen unbeabsichtigte Veränderungen an den übrigen 98% der Funktionalität unbemerkt bleiben. Weiterhin ermöglichen sie, das Design der Software laufend zu verbessern, zu vereinfachen oder auch nur vor Degeneration zu bewahren ohne dabei die Funktionalität zu verändern (Refaktorierung).
Unit-Tests entfalten jedoch ihren Nutzen nur, wenn sie sehr häufig ausgeführt werden können. Deshalb sollte jeder einzelne, wegen deren großer Anzahl, nur eine sehr geringe Laufzeit haben. Dieses setzt häufig voraus, dass sich eine Unit für ihre Tests vom Rest des Systems weitgehend abkoppeln lässt. Alleine diese verminderte Kopplung stellt bereits eine wichtige Verbesserung der Struktur des Quellkodes dar.

Aufwand

Die erheblichen Aufwände lassen sich bei hochwertigen Unit-Tests durch Einsparungen bei der Entwicklung (s.o.), der Detailspezifikation und der Dokumentation mehr als kompensieren. Da der Programmkode der Unit-Tests jedoch genau wie der Produktivkode von der Weiterentwicklung des Systems betroffen ist, sind an seine Qualität und Lesbarkeit die selben Anforderungen zu stellen, wie an den Produktivkode selbst.
Um die Aufwände zu verringern, müssen sich besonders bei größeren Systemen u.a. mit Hilfe geeigneter Programmierrichtlinien all jene Tests möglichst präzise herausfiltern lassen, die von einer konkreten Änderung am Produktivkode betroffen sein könnten.

Qualitätskriterien

Die Qualität von Unit-Tests äußert sich neben ihrer Ausführungsgeschwindigkeit einerseits im Umfang der Abdeckung, d.h. welche Klassen/Methoden besitzen Unit-Tests, und andererseits in der Qualität dieser Abdeckung. Diese wiederum äußert sich darin, dass bei einer logischen Veränderung am Produktivkode:

  • immer auch Unit-Tests fehlschlagen (möglichst wenige, weil sonst hier die Änderungskosten steigen),
  • die Namen aller fehlschlagenden Tests einen genauen Hinweis auf die konkrete Änderung geben (aufgrund einer einzigen Änderung dürfen also nur wenige Tests fehlschlagen, weil sonst diese Präzision verloren ginge).

Zur Kode-Qualität der Unit-Tests lassen sich noch einige spezielle Aussagen machen:

  • Unit-Tests müssen selbsterklärend und in sich abgeschlossen sein. Die abgeprüften Ergebnisse müssen alleine aus Set-Up und Testablauf verständlich sein und nicht ein Nebeneffekt von z.B. irgendwelchen bereits in einer Datenbank vorhandenen Daten.
  • Es muss aus den Tests eindeutig ersichtlich (automatisch auswertbar) sein, welche Klassen sie testen und welche sie nur zu Hilfszwecken benutzen.

Technische Hinweise, Referenzen

Die folgenden Referenzen stellen kein Qualitätsurteil dar. Sie sollen nur einen ersten Einstieg in Aspekte der Materie bieten.
Als Basis für automatisierte Unit-Tests werden heute in vielen Sprachen insbesondere die XUnit-Frameworks genutzt (s. z.B. JUnit für Java). Diese enthalten auch diverse Beispiele. Sie werden oft durch weitere Techniken wie Fake‑ oder Mock‑Objekte ergänzt. Jester ist ein Werkzeug, das JUnit-Tests durch automatische Änderungen am Quellkode testet.
junit ist eine aktive, internationale Diskussionsgruppe mit hochkarätigen Teilnehmern.
Als Literaturhinweise seien hier nur erwähnt:

IS-Rating: Planungssicherheit durch transparente Qualität