iX 11/2017
S. 126
Praxis
Softwareentwicklung
Aufmacherbild

Testdatenerzeugung mittels Testdatenfabriken

Industrielle Fertigung

Testdatenfabriken zum Testen komplexer Anwendungen sind schwierig in der Handhabung. Das Builder-Pattern und ein Codegenerator können den Aufwand wesentlich reduzieren.

Traditionell erzeugen automatisierte Tests ihre Daten entweder direkt im Testcode oder mittels spezieller Testdatenfabriken (zentral). In Softwareprojekten findet man beide Ansätze, die oft nur mäßig erfolgreich funktionieren. Denn beide Varianten haben Grenzen und bieten gegensätzliche Vor- und Nachteile. Builder-basierte Testdatenfabriken könnten das Dilemma auflösen, denn mit ihnen lassen sich die Vorteile kombinieren und die Nachteile beseitigen.

Ein optimal strukturierter Test durchläuft drei Phasen: Aufbau, Aktion und Prüfung. In der ersten Phase bereitet er das Szenario vor, das heißt, er versetzt das System in den benötigten Ausgangszustand. Dieser Vorgang umfasst etwa das Setzen der Systemzeit, Eintragungen in die Datenbank und die Vorbereitung von Daten, die als Parameter in der nächsten Phase zur Verfügung stehen sollen. In der zweiten Phase führt der Test die zu prüfende Funktion aus. Ein Test zur Orderfunktion eines Aktienhandelssystems löst beispielsweise einen einzelnen Auftrag aus. In der letzten Phase untersucht der Test, ob sich das System im gewünschten Zustand befindet. Im Wesentlichen vergleicht er dazu den Rückgabewert der Funktion mit dem erwarteten Wert oder kontrolliert Werte in einer Datenbank.

Dieser Artikel konzentriert sich auf die Aufbauphase, speziell auf das Erzeugen von Testdaten. Er beleuchtet die Vor- und Nachteile der beiden klassischen Varianten und wie der Einsatz von Builder-Klassen die unterschiedlichen Ansätze vereinen kann.

Lokal erzeugte Testdaten werden direkt im Code der einzelnen Tests angelegt. Die Stärke dieses Vorgehens: bessere Nachvollziehbarkeit. Ein Leser kann ihren Inhalt leichter verstehen, wenn er die zugehörigen Daten dort findet und somit in der Lage ist, alle relevanten Aspekte auf einen Blick zu erfassen. Das verkürzt den Aufwand einer späteren Fehlersuche deutlich. Allerdings leidet die Verständlichkeit, wenn die Menge an Daten pro Test zu groß wird. Die meisten dieser Informationen sind für die Lauffähigkeit des Systems zwar notwendig, für den konkreten Test jedoch nicht.

Den Überblick zu behalten, ist schwierig

So dürfte es für die Prüfung der erwähnten Orderfunktion in der Regel irrelevant sein, an welcher Börse die Aktie gehandelt wird. Dennoch muss der Entwickler diese Zuordnung beim Aufbau der Testdaten angeben, da sich eine Order immer auf einen Handelsplatz bezieht. Man kann leicht den Überblick verlieren, wenn sich ein Test über mehrere Bildschirmseiten erstreckt und zum überwiegenden Teil Daten aufbaut. Noch schlimmer wird es, wenn sich die Daten verschiedener, aber ähnlicher Tests nur in Kleinigkeiten unterscheiden und über weite Strecken mittels duplizierten Codes hergestellt werden.

Daraus erwachsen zwei Probleme: Zum einen muss der Entwickler lange suchen, bis er die Unterschiede in den Tests findet. Das ist beispielsweise notwendig, wenn er verstehen möchte, warum einer von mehreren ähnlichen Tests fehlschlägt. Zum anderen verschlechtert duplizierter Code die Wartbarkeit der Tests und der eigentlichen Anwendung. Umbauten und der Einbau neuer Features, die sich auf die Testdaten auswirken, sind dann aufwendig und fehlerträchtig, da die Änderungen wegen der Wiederholungen mehrmals durchgeführt werden müssen. Zumindest das zweite Problem lässt sich mit der zentralen Option lösen.