Weitere einfache, aber hilfreiche Tests überprüfen die Syntax von Bash-, Perl- und Python-Skripten, jedoch auch die von Konfigurationsdateien im XML- und Yaml-Format (Listing 3). Jeder einzelne Test erzeugt einen Fehlercode, wodurch das Testskript erfährt, ob er fehlgeschlagen ist. Weitere Beispiele sind automatisierte Tests von Konfigurationen für Apache HTTPD, ISC DHCPD, ISC Bind oder Postfix. All diese Anwendungen bringen bereits Funktionen mit, um eigene Settings zu testen. Selbst aufwändigere Szenarien lassen sich in einem Unittest abbilden, zum Beispiel automatisierte Tests für SSH-Konfigurationen [4].
Listing 3
Syntaxchecks
01 set -e
02 perl -c Skript.pl
03 bash -n Skript.sh
04 pylint -E Skript.py
05 xmllint Datei.xml
06 python -c "import yamlyaml.safe_load (open('Datei.yaml'))"
Diese Automation hat den großen Vorteil, dass sie Quellcode, Buildrezepte und Tests verknüpft. Schlagen die Tests fehl, baut das Buildskript ein Paket gar nicht erst. Die Tests sind stets dabei und das Buildskript führt sie immer mit aus. Arbeitet der Entwickler am Quellcode, fällt es ihm leicht, die Tests gleich mit anzupassen, sodass neue Funktionen sie gleich im Gepäck haben.
Systemtests
Da es bei Systemtests um das große Ganze geht, dauern sie meist etwas länger, beginnen sie doch mit der Installation des Programms auf einem Testsystem. Dort feuert die Testautomation dann verschiedene Checks von außen ab. Fehlerzustände stellt der Admin künstlich her, indem er das Testsystem vor dem Test gezielt manipuliert. Als Falschspieler bieten sich die IPtables-Regeln an, wenn sie alle oder gemeinerweise nur 50 Prozent der Netzwerkpakete verwerfen und so ein Netzwerkproblem simulieren. Eine robuste Anwendung sollte nicht kommentarlos abstürzen, sondern eine Wartungsseite anzeigen, bis die Datenbankverbindung wieder steht.
Ein Systemtest muss auch unbedingt die typischen operativen Aufgaben einbeziehen: einen Dienst starten, seinen Status überprüfen und den Dienst wieder beenden. Ein Reboot zeigt, ob nach dem Neustart wieder alle relevanten Dienste laufen und das System benutzbar ist. Wer sich diesen Test spart, sitzt auf einer tickenden Zeitbombe, die beim nächsten größeren Ausfall im Rechenzentrum den schnellen Wiederanlauf verhindert.
Ist ein Ausfall plötzlich akut, benötigt der Admin eine Möglichkeit, auf dem Testsystem an der bestehenden Automation vorbei beliebige Befehle auszuführen. Dafür empfehlen sich entweder SSH [5] oder sogar RSH [6], falls der Admin den SSH-Schlüsseln blind vertraut.
Von der Software-Entwicklung eingeführt, sind Versionskontrollsysteme wie SVN und Git inzwischen auch im Operations-Bereich fest etabliert. Zusammen mit einem Continuous-Integration-Server (CI) wie etwa Jenkins [7] und einem einfachen Buildskript wie zum Beispiel »svn2rpm« [8] lässt sich eine automatische Pipeline zwischen den Paketquellen, die in einem SVN liegen, und einem Yum-Repository aufbauen.
Der CI-Server steuert dabei alle notwendigen Schritte: Eine Änderung an den Quellen stößt einen Buildjob an, der auf einem dazu bestimmten Rechner, dem Buildagent, läuft. Der Buildjob erstellt die Software direkt im Versionskontrollsystem aus dem Quellcode, wobei auch die Unittests laufen. Dann schiebt er das fertige RPM-Paket zum Testen in ein Yum-Repository.
Schließt der Buildjob seine Aufgabe erfolgreich ab, stößt er einen Testjob für den Systemtest an. Dieser installiert das RPM-Paket auf einem Testserver und lässt die Systemtests dagegen laufen. Sind die erfolgreich, verschiebt der Testjob das RPM-Paket aus dem Test-Repository in ein Produktions-Repository und löst auf dem Produktivserver ein Update mit der neu erstellten und getesteten Software aus. Im Ergebnis entsteht eine Lieferkette (Abbildung 3), die automatisiert die Änderungen oder Aktualisierungen aus den Softwarequellen auf die produktiven Systeme bringt.
Der entscheidende Teil dieser Lieferkette sind die Testphasen. Der Buildprozess führt die Unittests mit aus, die Systemtests sind ein eigener Schritt im automatisierten Prozess.






