Der Betrieb lernt von den Entwicklern meist noch mehr:
- Kleine Schritte gehen (Incremental Improvement).
- Infrastruktur in Code umsetzen.
- Konsequent Versionskontrollsysteme benutzen.
- Denken wie ein Entwickler: Funktionen in Bibliotheken auslagern, richtige Abstraktion und so weiter.
- Anstelle von Spaghetticode mit langen Kommentaren lesbaren und wartbaren Code produzieren.
- Schnittstellen definieren.
- Unittests und Integrationstest umsetzen.
- Testautomation.
Dabei zeigt sich: Viele praktische Aspekte in der modernen Software-Entwicklung ergeben auch im administrativen Bereich Sinn. So teilen Entwicklung und Betrieb eines der wichtigsten Prinzipien: die testgetriebene Entwicklung [1].
Untested = broken
Die Grundidee besagt, dass alle nicht getesteten Funktionen entweder kaputt oder nicht implementiert sind. Während Entwickler viele verschiedene Arten von Tests kennen, reichen im Operations-Bereich meist zwei Testtypen aus: Unittests und Systemtests. Unittests überprüfen eine kleine Komponente, die Unit, in einer künstlichen Umgebung. Systemtests bringen die gesamte Anwendung in einer möglichst praxisnahen Form mit anderen Anwendungen oder deren Abhängigkeiten zusammen. Unittests durchleuchten also eher einzelne Codeteile, während Systemtests überprüfen, wie sich die Anwendung als Ganzes verhält.
Die beiden gegensätzlichen Testverfahren ergeben in ihrer Kombination eine gesunde Mischung aus Detailansicht und einem Blick aufs Ganze. Je nach Testsubjekt wählt der entwickelnde Admin den einen oder anderen Weg: Für Funktionen und Bibliotheken sowie Syntaxchecks greift er zu Unittests, die er auch problemlos auf dem Entwicklerdesktop ausführt.
Wenn möglich kann der Tester das Programm oder Tool in einem Unittest bereits mit Testdaten füttern, hier würde ein Entwickler schon von einem Integrationstest sprechen.
Unittests im Buildprozess
Damit Tests Vertrauen schaffen, müssen sie regelmäßig laufen, am besten automatisch und als Teil des Buildprozesses. Praktischerweise bietet Linux mit der Paketverwaltung bereits ein einfaches Buildsystem an, Tests lassen sich aber in alle Buildsysteme [2] integrieren. Die folgenden Beispiele für Unittests basieren auf RPM-Paketen und kommen aus der Infrastruktur-Entwicklung bei Immobilienscout24. Alle im Artikel vorgestellten Beispiele helfen beim automatischen Erstellen von Paketen.
Ein RPM-Paket besteht aus einer »SPEC« -Datei und den Quelldateien, einen guten Einstieg in den Eigenbau liefert [3]. Erstere dient als Rezept, um aus den Quellen ein Paket zu schnüren. Als Teil des Bauprozesses kann ein Entwickler dabei beliebigen Code ausführen. Eine typische »SPEC« -Datei folgt in etwa dem Schema aus Listing 1, das alle notwendigen Schritte enthält, um aus Softwarequellen ein Paket zu bauen und es zu installieren. In die Buildphase für das RPM (»%build« ) kann ein Admin die Unittests integrieren. Ein sehr deutliches Beispiel für deren Nützlichkeit ist der automatische Syntaxcheck für »sudo« -Regeln in Listing 2.
Listing 2
sudo-Regeln prüfen
01 [...]
02 BuildRequires: sudo
03
04 %build
05 set -e
06 visudo -c -f sudoers
07
08 %install
09 install -m 0644 sudoers -D %{buildroot}/etc/sudoers.d/%{name}
Listing 1
SPEC-Datei
01 Name: Beispiel
02 Version: 99
03 Requires: foo
04 Source: %{name}-%{version}.tar.gz
05
06 %prep
07 %setup -q
08
09 %build
10 %configure
11 make
12
13 %install
14 install Beispiel %{buildroot}/Beispiel
15 install Beispiel %{buildroot}/Beispiel
16
17 %files
18 %defattr(-, root, root, -)
19 /*
Dieser Test ist wichtig, weil »sudo« bei Syntaxfehlern generell die Mitarbeit verweigert. Ein Admin mit einer defekten »sudoers« -Datei hat sich den Ast abgesägt, auf dem er sitzt, weil er die Zugriffsrechte verliert, um das Problem zu beheben. Steigt das Skript in der Buildphase mit einem Fehler aus, wofür »set -e« sorgt, bricht »rpmbuild« automatisch den Bauprozess ab.





