Desintegrationstests

Desintegrationstests

Software ist nie perfekt. Ausfälle von Software machen Schlagzeilen und schädigen den Ruf von Unternehmen und Organisationen. Ein ziemlich spektakuläres Beispiel für ein solches Versagen führte zum Verlust des Mars Climate Orbiter.

Die Mission dieser Raumsonde, die rund 655 Millionen USD kostete, war die Untersuchung der Atmosphäre und des Klimas unseres planetarischen Nachbarn. Am 23. September 1999 näherte sich die Sonde dem Mars in einem falschen Winkel und desintegrierte. Die Ursache für den Verlust des Mars Climate Orbiters wurde am 30. September 1999 veröffentlicht:

Die vorläufigen Ergebnisse des Peer Reviews deuten darauf hin, dass ein Team englische Einheiten (zum Beispiel Zoll, Fuß und Pfund) verwendete, während das andere Team metrische Einheiten für eine Schlüsseloperation der Raumsonde verwendete. Diese Information war entscheidend für die Manöver, die erforderlich waren, um das Raumfahrzeug in die richtige Marsumlaufbahn zu bringen.

Wir können davon ausgehen, dass die beiden im obigen Bericht erwähnten Teams ihre einzelnen Komponenten der Software (isoliert von der jeweils anderen Komponente) rigoros mit Unit Tests getestet haben. In Anbetracht des Ergebnisses müssen wir jedoch davon ausgehen, dass kein einziger Integrationstest durchgeführt wurde, um sicherzustellen, dass die beiden Komponenten bei der gemeinsamen Verwendung korrekt funktionieren. Es scheint, dass diese beiden Komponenten zum ersten Mal in der Umlaufbahn des Mars integriert zusammengearbeitet haben. Dabei handelt es sich nicht um einen Integrationstest, sondern eher um einen „Desintegrationstest“.

Dr. Edward Weiler, Associate Administrator for Space Science bei der NASA, machte eine interessante Beobachtung in den vorläufigen Ergebnissen des Peer Reviews:

Das Problem hier war nicht der Fehler, es war das Versagen der Systemtechnik der NASA und der Kontrollen in unseren Prozessen, um den Fehler zu erkennen. Das ist der Grund für den Verlust der Raumsonde.

Die Ursache für den Verlust des Mars Climate Orbiters war nicht nur ein technischer Fehler im Quellcode der Navigationseinheit, sondern wurzelte vielmehr in Kommunikations- und Prozessproblemen. Hätten die beiden Teams miteinander kommuniziert, wäre ihnen bewusst gewesen, dass das eine Team metrische und das andere Team englische Einheiten verwendet. Und hätte der Prozess neben dem isolierten Testen der beiden Komponenten auch Integrationstests vorgesehen, wäre der Fehler ebenfalls aufgedeckt worden.

Eine der wichtigsten Aufgaben beim Softwaretest ist es, den kleinsten Umfang zu finden, in dem ein Test implementiert werden kann. Je kleiner der Umfang ist, in dem ein Test ausgeführt wird, desto schneller kann er ausgeführt werden und desto präziser ist sein Ergebnis. Unit Tests verifizieren eine Code-Einheit isoliert von allen Abhängigkeiten. Integrationstests überprüfen das Zusammenspiel von zwei oder mehr kollaborierenden Objekten oder Teilsystemen in Isolation vom Rest des Systems. Edge-to-Edge-Tests führen die Software möglichst durchgängig in einem einzigen Prozess aus (und zwar ohne Verwendung eines Webbrowsers oder eines Webservers). End-to-End-Tests oder Systemtests betrachten das gesamte System und senden im Falle einer Webanwendung eine HTTP-Anfrage von einem Webbrowser an einen Webserver, auf dem die Software läuft, um die zurückgesendete HTTP-Antwort zu untersuchen.

In einem anderen Artikel habe ich geschrieben, dass

Akzeptanztests sagen Ihnen, dass Sie das richtige Produkt bauen, indem sie sicherstellen, dass die Software das tut, was sie tun soll. Unit Tests sagen Ihnen, dass Sie das richtige Produkt bauen, indem sie sicherstellen, dass der Code korrekt funktioniert.

Es ist einfach – und verführerisch – Akzeptanztests mithilfe von Werkzeugen zu implementieren, die die Software end-to-end testen. Gerade Teams, für die das Testen neu ist und/oder die mit Legacy-Software zu tun haben, die nicht auf Unit-Ebene testbar ist, tappen oft in die Falle, die Kerndomänenlogik ihrer Anwendung über das Frontend zu testen. Diese indirekte Art des Testens ist langsam und anfällig. Sie ist langsam, weil die gesamte Anwendung in einem großen Umfang ausgeführt wird, um einen Aspekt der Anwendung zu testen, der in einem kleinen Umfang getestet werden sollte. Sie ist anfällig, weil die Tests für die Domänenlogik angepasst werden müssen, wenn sich die HTML-Templates des Frontends ändern. Erschwerend kommt hinzu, dass diese Tests in einem Scope durchgeführt werden, der so groß ist, dass ein fehlgeschlagener Test dem Entwickler nur mitteilt, dass etwas nicht funktioniert, ohne Informationen zu liefern, die auf die eigentliche Ursache hinweisen. Obwohl es einen Platz für diese Art von Tests im Testmix für eine Anwendung gibt, zum Beispiel um die Cross-Browser-Kompatibilität zu testen, wäre ein Team schlecht beraten, sich ausschließlich auf End-to-End-Tests zu verlassen, da diese umständlich zu schreiben und zu warten, fehleranfällig und langsam in der Ausführung sind.

Akzeptanztests sollten stattdessen mit Edge-to-Edge-Tests implementiert werden. Diese sind einfacher zu schreiben und schneller auszuführen als altmodische Ende-zu-Ende-Tests. Noch wichtiger ist, dass sie nur minimale Wartung erfordern. Am wichtigsten ist, dass sie sehr zuverlässige Ergebnisse liefern.

Wenn die Architektur der Software sowohl Unit-Tests als auch Edge-to-Edge-Tests zulässt, dann wird es auch einfach sein, die Praktiken der experimentellen Entwicklung und des Testens in der Produktion zu übernehmen, über die Eric Ries in seinem Buch „The Lean Startup“ geschrieben hat. Das Versprechen, sowohl das Geschäftsmodell als auch die Software, die es umsetzt, agil entwickeln zu können, sollte für Unternehmen Grund genug sein, in eine moderne, stark entkoppelte Softwarearchitektur zu investieren. Und wenn die Mitglieder des Software-Entwicklungsteams gut kommunizieren, sowohl untereinander als auch mit den anderen Stakeholdern, dann gibt es nicht viel, was den Erfolg des Projekts wirklich behindern kann.