Für Infrastrukturtest bieten sich verschiedene Verfahren an. Aus der Softwareentwicklung sind Blackbox - und Whitebox-Tests bekannt. Bei der ersten Variante wird das, was man testen möchte ausschließlich von außen (als Black Box) betrachtet, und das Verhalten der Komponenten wird über seine Schnittstellen gegenüber einer Spezifikation bewertet.

Whitebox ...

Bei Whitebox-Tests fließen Detailinformationen der zu testenden Komponente ein, d.h. man muss also in die Komponente hereinschauen können, um den Test durchzuführen.

In den letzten Posts über serverspec haben wir uns mit Whitebox-Testing beschäftigt. Hier beschreiben wir in einer Spezifikation den Detailaufbau eines Servers, und serverspec prüft für uns diese Dinge ab. Dazu muss serverspec natürlich in/auf den Server schauen.

Wenn der Server beispielsweise einen Webservice bereitstellt, können wir mit serverspec prüfen,

  • ob die Pakete für Middleware und Applikation installiert sind,
  • ob die Applikation ihre Konfigurationsdateien besitzt,
  • und diese korrekt sind,
  • ob der Service startet und einen Netzwerkport belegt,
  • und vieles mehr.

Damit ist nur leider nicht gesagt, dass der Webservice auch wie gewünscht funktioniert. Mit dem Whitebox-Test haben wir nur die Grundlagen abgeprüft, die überhaupt erst einmal notwendig sind.

Man könnte im nächsten Schritt mit einem Tool wie curl oder wget innerhalb des Servers einen HTTP-Call absetzen und das Ergebnis prüfen. Die Funktionsfähigkeit kann von außen betrachtet aber immer noch scheitern, etwa weil die Netzwerkkonfiguration nicht stimmt oder iptables den Zugriff verhindert.

... und Blackbox

Das wiederum lässt sich mit einem Test von außen abprüfen. Wenn ein anderer Server den Service abfragt und ein korrektes Ergebnis erhält, kann man schon eher sicher sein, dass alles korrekt ist.

Da serverspec erweiterbar ist, lassen sich prinzipiell auch Blackbox-Tests durchführen. Ein einfaches - allerdings unschönes - Beispiel nutzt das Kommandozeilentool curl um einen HTTP-Call zu platzieren und Daten aus der Ausgabe zu prüfen:

describe command 'curl http://appserver:8080/test' do
  it { should return_exit_status 0 }
  its(:stdout) { should match /^success$/ }
end

Das sollte funktionieren, wandelt aber den deklarativen Ansatz von serverspec in einen imperativen um: Wir beschreiben nicht eine Webresource, sondern konstruieren ein command, um sie abzufragen. Vor allem wenn beim curl-Aufruf Parameter übergeben werden, vielleicht noch über HTTP POST, wird der Einzeiler länger und unschöner.

Geschmacksprobe: Infrataster

Glücklicherweise gibt es ein Projekt, das den Blackbox-Ansatz in rspec-Art und Weise umsetzt, Infrataster. Dies ist eine Erweiterung auf rspec, die verschiedene Typen einführt um Calls abzusetzen und das Ergebnis abzuprüfen. Dabei werden Webcrawler-Frameworks aus der Ruby-Welt eingesetzt um dennoch bei einer lesbaren Testspezifikation bleiben zu können.

Das sieht dann beispielsweise so aus:

describe server(:app) do
    describe http('http://appserver:8080/test') do
        it "responds content including 'success'" do
            expect(response.body).to include('success')
        end
    end
end

Hier wird im äußeren describe-Block der zu testenden Server angegeben (:app, s.u.), im inneren Block die Ressource (appserver:8080/test), und die Expectations, z.B. bezüglich der Rückgabe.

Infrataster kann dabei die Rückgabe auch detaillierter prüfen, etwa ob bestimmte Response-Header gesetzt sind, hier, ob der Content-Type text/html entspricht:

        it "responds as 'text/html'" do
            expect(response.headers['content-type']).to match(%r{^text/html})
        end

Außerdem kann man bei Konstruktion des Calls auch Parameter mitgeben, z.B.

    describe http(
            'http://appserver:8080/foo/app',
            method:   :get,
            params:   {'foo'   => 'bar'},
            headers:  {'USER'  => 'VALUE'}
    ) do
    ...
    ...

Damit lassen sich Webservices auch von außen gut testen. Weitere Post zeigen die Verdrahtung zu den Zielservern (":app"), die Nutzung von Proxies, wie Infrataster aufgebaut ist, und wie man damit ein reales Testszenario aufsetzt.

Beides zusammen, FTW!

Weder Blackbox- noch Whitebox-Tests sind für sich genommen ausreichend. Wenn innerhalb der Komponente alles in Ordnung ist (Whitebox) heisst das nicht automatisch, dass ihr Verhalten nach außen wie gewünscht funktioniert.

Umgekehrt kann man aus einem fehlschlagenden Blackbox-Test noch nicht ermitteln, woran es eigentlich scheitert, d.h. der Fehler ist erkennbar, aber nicht lokalisierbar.

Um Infrastrukturkomponenten qualitativ testen zu können, sind sowohl White- als auch Blackbox-Tests sehr sinnvoll. Hier ist die Kombination von serverspec und Infrataster wirksam und empfehlenswert!

Andreas