Johannes Seitz

Voraussichtliche Lesedauer: 6 Minuten

Techblog

Techniken der IT-Sanierung: Der Golden Master Test

Ein klassisches Dilemma der IT-Sanierung ist, dass keine automatischen Regressionstests existieren, mit denen man den Code gefahrlos umstrukturieren kann. Die Umstrukturierung aber ist die Voraussetzung, um Testbarkeit des Codes herzustellen. Eine Möglichkeit, Testbarkeit herzustellen, ist auf die Refactoringfunktionen der IDE zu vertrauen. Diese sind ziemlich gut darin, die Semantik des Codes zu wahren. Aber die…

Techblog

Ein klassisches Dilemma der IT-Sanierung ist, dass keine automatischen Regressionstests existieren, mit denen man den Code gefahrlos umstrukturieren kann. Die Umstrukturierung aber ist die Voraussetzung, um Testbarkeit des Codes herzustellen.

Eine Möglichkeit, Testbarkeit herzustellen, ist auf die Refactoringfunktionen der IDE zu vertrauen. Diese sind ziemlich gut darin, die Semantik des Codes zu wahren. Aber die Möglichkeiten der IDE Refactorings sind recht eingeschränkt und gerade bei größeren Änderungen schleichen sich trotzdem gerne subtile Regressionen ein. Für solche Refactorings bietet der Golden Master Test ein schnelles und umfassendes Sicherheitsnetz gegen Regressionen.

Der Name “Golden Master” bezieht sich auf das Stadium, in der Software als “fertig” gilt. Der Golden Master Test versucht, das Verhalten der Applikation in diesem Stadium in Form eines Charaktisierungstests festzuhalten. Da jede Applikation Inputs in einer Form entgegennimmt und immer auf die eine oder andere Art einen Output erzeugt, nutzt der Golden Master Test diese Schnittstellen, um eine möglichst flächendeckende Charakterisierung der Applikation zu erreichen.

Einen Golden Master Test erstellen

Zur Erstellung eines Golden Master Tests müssen zunächst die Ausgaben der Applikation als Vorlage für den Vergleich gespeichert werden. Dabei kann es hilfreich sein, auch die zugehörigen Eingaben in eine Datei zu speichern, die sich der jeweiligen Ausgabendatei einfach zuordnen lässt. Beim Golden Master Test selbst wird anschließend der gleiche Input verwendet, um einen Output zu erzeugen. Dieser wird mit dem “richtigen” Output aus der aufgezeichneten Golden Master Datei verglichen, um Abweichungen festzustellen.

Den Input aufzeichnen

Zur Aufzeichnung des Inputs liegen uns je nach Schnittstellen verschiedene Möglichkeiten vor. Dabei gibt es Schnittstellen, die einfach zu automatisieren sind, etwa CLIs, oder Schnittstellen, die notorisch schlecht zu automatisieren sind, zum Beispiel exotische GUI Frameworks. Tools wie SoapUISeleniumBetamax und weitere ‘”Record and replay”-Werkzeuge können hierbei sehr hilfreich sein.

Falls die Applikation Zufallszahlen nutzt oder zum Beispiel das jeweils aktuelle Datum verwendet, ist das Aufzeichnen des Inputs erschwert, denn diese Werte sind in der Regel nicht Teil des direkten Inputs, sondern werden indirekt über das Betriebsystem oder Framework in die Applikation gegeben.

In einfachen Fällen kann man hier Testbarkeit erreichen, indem die indirekten Inputwerte zu direkten Inputwerten gemacht werden. Erzeugt man beispielsweise das aktuelle Datum nicht direkt im Code sondern über eine Factory, lässt sich diese im Test recht einfach durch ein Test Double ersetzen. Das Test Double spielt dann beim Golden Master Test die Werte zur Zeit der Aufzeichnung aus der Input-Werte Datei wieder ab.

In komplexeren Fällen, zum Beispiel wenn die entsprechende Klasse an sehr vielen Stellen genutzt wird, muss man in die Trickkiste greifen. Beim Datum könnte beispielsweise die Uhr des Rechners vor dem Test auf einen bestimmten Wert zurückgesetzt werden.

Ein letzter Ausweg kann auch sein, der Applikation eine eigene Version der Bibliotheksklasse unterzujubeln, wie es Michael Feathers auf S. 377ff in “Working Effectively with Legacy Code” beschreibt. In dynamischen Sprachen ist diese Form des ‘Monkey Patching’ natürlich einfach. Bei statischen Sprachen wie Java muss für diesen Trick zum Beispiel die eigene java.util.Date Klasse im Classpath vor der des JDK geschoben und damit im Test ausgetauscht werden.

Wenn Zufallszahlen zum Einsatz kommen, kann man auch den Seed-Wert eines Pseudo-Random Number Generators (PRNGs) aufzeichnen und im Test den aufgezeichneten setzen, um bei jeder Testausführung die gleichen Zufallswerte zu erzeugen.

Den Output aufzeichnen

Der Output des Programms kann anschließend in einer Datei festgehalten werden. Je nach Applikation kann hier ein geniererter Report, die Umleitung von STDOUT in eine Datei, ein Datenbankdump oder die Aufzeichnung einer HTTP-Konverstation als Output dienen. Vor allem “Plain Text” Formate eignen sich gut für die Aufzeichnung.

Als letzter Schritt bleibt der Vergleich des Outputs aus dem sanierten System mit dem Output aus der Aufzeichnung. Bei Textdateien kann der Vergleich mit “diff”-Algorithmen einen Hinweis auf eventuelle Fehler herausstellen. Der Test sollte aber in jedem Fall selbstverifiziernd (self-verifying) sein, also keine manuelle Inspektion der Differenzen erfordern.

Bei binären Formaten kann der Vergeich von Prüfsummen sinnvoll sein. Dann hat man aber nur noch ein Feedback, dass ein Fehler vorliegt, und nicht um welchen es sich handelt.

Vor- und Nachteile des Golden Master Tests

Der Golden Master Test kann die notwendige Sicherheit geben, um einen großen Umbau der Applikation hin zu besserer Testbarkeit zu ermöglichen. Oftmals kann man mit Tricks die oben genannten Probleme auf Applikationsebene (vor allem indirekte Eingaben) einfacher lösen als die Probleme auf der Klassenebene.

Leider ist der Golden Master Test sehr fragil, wenn neue Features eingeführt werden, die die Ausgaben des Systems verändern. Die Erweiterung der aufgzeichneten Golden Master Dateien um die neuen Funktionen kann dabei sehr aufwendig werden und bei der erneuten Aufzeichnung der Ausgaben verliert man leider an Sicherheit.

Der Golden Master Test ist auch definitiv kein Ersatz für feingranulare Tests. Das Feedback des Golden Master Tests ist wesentlich unspezifischer als das Feedback aus einer Klasse, die in Isolation getestet wird. Und die Umstruktuierung, die es einer Klasse erlaubt, in Isolation getestet zu werden, führt oftmals zu einer wesentlichen Verbesserung des Systemdesigns.


Das ist Teil 1 meiner Serie über Techniken der IT-Sanierung. In Teil zwei schreibe ich darüber, wie man ein großes Refactoring in kleinen Schritten realisiert. 

Über den Autor

Johannes Seitz