(2) assert normalize( [1, 0, 0] ) = [1, 0, 0]
(3) assert normalize( [0, 2, 0] ) = [0, 1, 0]
(4) assert normalize( [3, 0, 4] ) = [0.6, 0, 0.8]
Das Schlüsselwort
prüft, ob eine gegebene Aussage wahr ist oder nicht; falls nicht, produziert sie einen Fehler, der dem Programmierer einen Hinweis darauf gibt, dass sein Test nicht erfolgreich war. Obiger Testfall überprüft die Methode normalize
demzufolge anhand von drei Werten. Schlägt keine der drei Überprüfungen fehl, muss normalize
also korrekt, das heißt ohne Fehler, sein…
Wirklich?
Nein, natürlich nicht. Ein Testfall kann nämlich nur überprüfen, ob eine Methode Fehler enthält – er kann nicht prüfen, ob sie fehlerfrei ist! Unsere normalize
-Methode ist ein wunderbares Beispiel hierfür, denn sie enthält einen Fehler (der dem aufmerksamen Leser natürlich schon längst aufgefallen ist): Wird als Eingabe der Nullvektor, also der Vektor [0, 0, 0] mit der Länge 0, verwendet, findet eine Division durch 0 statt und produziert damit einen Fehler. Der Nullvektor ist eigentlich nicht normierbar; da Computer aber dennoch mit diesem Fall umgehen können müssen, wird üblicherweise vereinbart, dass der normierte Nullvektor wieder der Nullvektor ist. Die Funktion normalize
müsste demzufolge folgendermaßen aussehen:
(2) l ∈ R, l ← sqrt( v02 + v12 + v22 )
(3) if l = 0:
(4) return [0, 0, 0]
(5) else:
(6) return [v0/l, v1/l, v2/l]
Um dieses Versäumnis als Fehler zu entdecken, muss der Testfall auch entsprechend angepasst werden:
(2) assert normalize( [1, 0, 0] ) = [1, 0, 0]
(3) assert normalize( [0, 2, 0] ) = [0, 1, 0]
(4) assert normalize( [3, 0, -4] ) = [0.6, 0, -0.8]
(5) assert normalize( [0, 0, 0] ) = [0, 0, 0]
Wünschenswert wäre natürlich, wenn ein Test gleich alle möglichen Eingaben überprüfen würde. Dem steht allerdings entgegen, dass es davon in der Regel ziemlich viele gibt; allein die Anzahl der möglichen dreidimensionalen Vektoren, die ein Computer darstellen kann, ist viel zu groß, um sie in vertretbarer Zeit zu überprüfen. Man kann sich also nur einige wichtige Werte in Grenzbereichen (im Falle der dreidimensionalen Vektoren sind das zum Beispiel der Nullvektor, Vektoren mit nur einer nichtleeren Koordinate, mit zwei nichtleeren Koordinaten) und einige weitere Testwerte heraussuchen und die Korrektheit der zu testenden Komponente mit diesen Werten überprüfen. Schlagen derartige Tests nicht fehl, ist das zumindest ein Hinweis darauf, dass keine allzu groben Fehler in der Komponente vorhanden sind – Fehlerfreiheit beweist das jedoch wie gesagt nicht!
Die gesamte Funktionalität eines Programms lässt sich mit Komponententests natürlich nicht überprüfen, da jene erst durch das Zusammenspiel vieler Komponenten entsteht. Komponententests können demzufolge nur benutzt werden, um die Basisfunktionalitäten eines Programms (etwa in Form von Methoden) zu testen – aber das ist immerhin besser als nichts und führt in Kombination mit weiteren Testverfahren (Stichworte: Integrationstests, Systemtests) dazu, dass immerhin die gröbsten Fehler gefunden werden können.
Die Eigenschaft von Komponententests, dass sie lediglich Fehler finden, aber keine Fehlerfreiheit nachweisen können, gilt für sämtliche Testverfahren, egal ob manuell oder automatisiert. Das ist auch einer der Gründe, warum selbst in kommerziell vertriebener und viel getesteter Software Fehler enthalten sind: Es ist schlicht nicht möglich, sämtliche Fehler in einem Programm im Voraus zu entdecken (außer, die Korrektheit des Codes wird formal bewiesen – aber das ist ein ganz anderes Kapitel…). Wenn also das nächste mal ein Programm ein Fehlverhalten aufweist, welches doch eigentlich vorher schon hätte bemerkt und beseitigt werden müssen, immer daran denken: Programmierer sind auch nur Menschen. Und machen wie alle anderen auch Fehler.
Kommentare (12)