Welcher Programmierer hätte nicht gern einen persönlichen Assistenten, der nach Änderungen kontrolliert, ob alles so funktioniert, wie es soll? Software testen kostet viel Zeit, ebenso die Fehlersuche. Um keine neuen Fehler in ein funktionierendes System einzubauen, scheuen viele Programmierer wichtige strukturelle Änderungen.
Die Antwort auf diese Probleme sind Unit-Tests. Sie sollen kontrollieren, ob ein kleines Stück Code genau das tut, was der Entwickler möchte. Der Test selbst ist ein Programm, das den zu testenden Code ausführt, Rückgabewerte vergleicht und etwaige Nebeneffekte aufdeckt. Der Kasten "Warum testen?" liefert weitere Argumente fürs richtige Testen von Software.
Unit-Tests werden oft mit anderen Formen von Software-Tests verwechselt. Ein Unit-Test hat nichts mit einem funktionalen Test zu tun, bei dem das Verhalten einer Software an den äußeren Schnittstellen (wie dem Userinterface) untersucht wird. Es geht beim Unit Testing darum, sich zu vergewissern, dass die einzelnen Bestandteile des Code nach Wunsch funktionieren. Aus diesem Grund wird Unit Testing oft auch als Developer Testing bezeichnet.
Tests planen
Wenn der Programmierer damit beginnt, Unit-Tests zu schreiben, ist eine seiner wichtigsten Fragen, wie viele und welche Tests nötig sind. Natürlich kann er jede einzelne Methode ausführlich untersuchen und damit einen Großteil der potenziellen Fehler vermeiden. Der notwendige Aufwand steht aber oft nicht mehr im Verhältnis zum Nutzen und schreckt daher viele davon ab, überhaupt zu testen.
Es geht beim Testen also zuerst um jene Funktionen, die das höchste Fehlerrisiko aufweisen. Besonders wichtig ist es, Ausnahmebedingungen, Sonderfälle und Grenzbereiche zu überprüfen, da sich hier am häufigsten Fehler verstecken.
Im Lieferumfang enthalten
Das Unit Testing Framework »Test::Unit« ist seit Ruby 1.8 Bestandteil der Standarddistribution. Das früher verwendete Modul »runit« existiert weiterhin als Wrapper um »Test::Unit«, der Rückwärtskompatibilität gewährleistet.
require 'test/unit'
class TestFactorial < Test::Unit::TestCase
def test_calc
end
end
Dieser Code soll ein Programm untersuchen, das die Fakultät einer Zahl berechnet. Ausgangspunkt für den Testprogrammierer ist zunächst das Testmodul. Die Testklasse leitet sich von »Test::Unit ::TestCase« ab. Alle Methoden, die mit »test« beginnen, arbeitet das Test-Framework automatisch ab, sobald der Ruby-Interpreter die Datei ausführt.
Jeder erfolgreiche Test wird durch einen Punkt dargestellt (Abbildung 2). Ein »F« steht für Failure (Versagen) und signalisiert, dass der Test nicht die erwarteten Rückgabewerte liefert. Das »E« ist die Kurzform für Error (Fehler) und bedeutet, dass innerhalb des Tests ein Programmfehler aufgetreten ist, beispielsweise eine Ausnahme. Die letzte Zeile informiert über die Anzahl der Tests, der Assertions und der aufgetretenen Fehler.