Legacy-Software ohne Tests
Häufig stehen Entwickler:innen vor der Herausforderung, automatisierte Tests für Legacy-Software zu schreiben. Als die Software entwickelt wurde, waren entweder die Test-Frameworks nicht reif genug oder die Programmiersprache, wie z.B. Delphi, war nicht sonderlich für die Testautomatisierung geeignet. Deshalb wurde in der Vergangenheit häufig manuell getestet, ohne Aufwand in die Testautomatisierung zu investieren. Dass die Entwickler:innen oder Teams, die die Software ursprünglich entwickelt haben, nicht mehr verfügbar sind, macht das Leben der heute für die Wartung verantwortlichen Entwickler:innen nicht leichter.
Wie können wir uns minimal absichern?
Viele Legacy-Systeme basieren auf folgendem Architekturmuster: Ein Frontend, das in Delphi, Visual C++ oder C# geschrieben ist. Dieses Frontend kommuniziert über eine direkte Socket-Verbindung und einem proprietären (Binary-)Protokoll mit dem Java-Backend oder umgeht das Backend komplett und greift direkt auf die Datenbank zu. I.d.R. verfügen die Systeme über keine Schnittstelle, gegen die sich automatisierte Tests programmieren lassen.
Oder doch? So gibt es fast immer eine GUI für die Benutzer des Systems. Können wir irgendwie Maus- oder Tastatur-Events generieren? Die Antwort lautet „Ja“. Im Windows-Umfeld gibt es eine Reihe von Tools zur Simulation von Benutzerinteraktionen über Maus und Tastatur. Ein Tool, mit dem wir gute Erfahrungen gemacht haben, AutoIt.
AutoIt bietet eine BASIC-ähnliche Sprache, die nicht nur Tastatur und Maus-Events erzeugen, sondern auch gezielt GUI-Elemente von Windows ansprechen kann. Das folgende Codefragment zeigt ein einfaches Beispiel, wie sich der Windows-Taschenrechner mit Hilfe von AutoIt fernsteuern lässt:
#include <Constants.au3>
; Run the calculator
Run("calc.exe")
; Wait for the calculator to become active. The classname
; "CalcFrame" is monitored instead of the window title
WinWaitActive("[CLASS:ApplicationFrameWindow]")
; Now that the calculator window is active type the values 2 x 4 x 8 x 16
; Use AutoItSetOption to slow down the typing speed so we can see it
AutoItSetOption("SendKeyDelay", 400)
Send("2*4*8*16=")
Sleep(2000)
; Add assertion and output the result
; Now quit by sending a "close" request to the calculator
; window using the classname
WinClose("[CLASS:ApplicationFrameWindow]")
; Now wait for the calculator to close before continuing
WinWaitClose("[CLASS:ApplicationFrameWindow]")
Mit Hilfe von AutoItX4Java ist es außerdem möglich, Tests direkt in Java und basierend auf modernen Test-Frameworks wie JUnit oder TestNG zu schreiben:
@Test
void notepadAutoItTest() {
String notepad = "[CLASS:Notepad]";
String testString = "this is a test.";
AutoItX autoIt = new AutoItX();
int result = autoIt.run("notepad.exe");
autoIt.winActivate(notepad);
autoIt.winWaitActive(notepad);
autoIt.send(testString);
assertTrue(autoIt.winExists(notepad, testString));
autoIt.winClose(notepad, testString);
autoIt.winWaitActive("Notepad");
autoIt.send("{ALT}n");
assertFalse(autoIt.winExists(notepad, testString));
}
Die Testautomatisierung mit AutoIt ist immer dann eine Option, wenn ein Altsystem ohne Tests nachträglich abgesichert werden soll. Für den Start reichen einige Happy-Path-Tests, die nach und nach um Tests für neue Features oder sich ändernde Anforderungen ausgebaut werden.