< HowToLifters002 | Entwicklungs-HOWTO
TODO (mlunzena) Was sind Unit-Tests? Wofür sind sie gut? Welches Tool wird verwendet?
Rufe in deiner Stud.IP-Working-Copy folgendes Kommando im Terminal auf:
php test/all_tests.php
Dieses Kommando durchsucht das Test-Verzeichnis nach Unit-Tests und führt diese aus. Daraufhin erhält man als Ausgabe die Zahl der ausgeführten und erfolgreichen Tests. Das sieht dann z.B. so aus:
All tests OK Test cases run: 10/10, Passes: 186, Failures: 0, Exceptions: 0
Ein Fehler würde in etwa so aussehen:
All tests 1) at [/test/lib/classes/assets_class_test.php line 43] in test_class_should_exist in AssetsTestCase FAILURES!!! Test cases run: 10/10, Passes: 185, Failures: 1, Exceptions: 0
Als Beispiel werden wir einen kleinen Test für die Funktion #words schreiben, die sich in der Datei lib/functions.php befindet.
Der Unit-Test-Runner, den wir oben ausführten, findet Test-Dateien in den Verzeichnissen test/lib und test/lib/classes. Dabei müssen die Namen dieser Dateien auf test.php enden.
In unserem Beispiel legen wir also eine Datei test/lib/functions_test.php an. Per Konvention sollen Tests, die sich auf Code in lib beziehen, im Verzeichnis test/lib liegen, und Tests, die sich auf Klassen aus lib/classes beziehen, im Verzeichnis test/lib/classes.
Jeder Unit-Test sieht minimal so aus:
Man halt also eine Klasse, die von UnitTestCase abstammt, und die Test-Methoden enthält, deren Name mit test beginnt. Der Name sollte andeuten, was man eigentlich gerade testet. Er darf gerne lang sein. Niemand wird diese Methoden per Hand aufrufen müssen.
In unserem ersten Test wollen wir den happy path der Funktion #words testen. Schauen wir uns noch einmal diese Funktion an:
Diese Funktion erlaubt es also offenbar, aus einem String ein Array zu machen, das die Wörter des Strings als Elemente hat.
Damit sieht der erste Test so aus:
In diesem Test wird ein String mit drei Wörtern angelegt, dann an #words verfüttert, und zum Schluss mit Hilfe der Methode #assertEqual verglichen. Ist diese Assertion wahr, ist der Test erfolgreich.
Ausserdem erkennt man gut das four phase test pattern. Die Kommentare trennen die 4 Phasen eines Tests. Unter "fixture" versteht man die Ausgangssituation, die geschaffen werden muss, um den Test auszuführen. In unserem sehr einfachen Beispiel ist dafür nichts notwendig. In der "exercise"-Phase wird dannn das zu testende Verhalten herbeigeführt, was in diesem Fall dem Aufruf der Funktion #words entspricht. Danach wird überprüft, ob das Ergebnis des Verhaltens den Erwartungen entspricht. Und ganz am Ende räumt man alles ab, damit der nächste Test in einer klar definierten Umgebung ablaufen kann. Bei unserem Test ist dafür nichts zu tun. Auf die Phasen 1 und 4 (Fixture-Setup und -Teardown) wird weiter unten vertieft eingegangen.
Die kleinste Einheit eines Unit-Tests ist die Assertion. Im Beispiel wollten wir sicherstellen, dass die Funktion tatsächlich das erwartete Array zurückliefert. UnitTestCase#assertEqual ist erfolgreich, wenn der erste Parameter == dem zweiten Parameter ist.
Es gibt eine noch viele weitere Assertions und selbstverständlich kann der Programmierer jederzeit durch Erweiterung der Klasse UnitTestCase neue hinzufügen.
Die grundsätzlichen Assertions werden in der folgenden Tabelle aufgelistet:
| assertTrue($x) | schlägt fehl, es sei denn $x entspricht true |
| assertFalse($x) | schlägt fehl, es sei denn $x entspricht false |
| assertNull($x) | schlägt fehl, es sei denn $x ist nicht gesetzt |
| assertNotNull($x) | schlägt fehl, es sei denn $x ist gesetzt |
| assertIsA($x, $t) | schlägt fehl, es sei denn die Klasse oder der Typ von $x entspricht $t |
| assertNotA($x, $t) | schlägt fehl, es sei denn die Klasse oder der Typ von $x entspricht nicht $t |
| assertEqual($x, $y) | schlägt fehl, es sei denn $x == $y ist wahr |
| assertNotEqual($x, $y) | schlägt fehl, es sei denn $x == $y ist falsch |
| assertWithinMargin($x, $y, $margin) | schlägt fehl, es sei denn $x und $y liegen weniger als $margin auseinander |
| assertOutsideMargin($x, $y, $margin) | schlägt fehl, es sei denn $x und $y liegen mehr als $margin auseinander |
| assertIdentical($x, $y) | schlägt fehl, es sei denn $x === $y für primitive Variablen, $x == $y für Objekte desselben Typs |
| assertNotIdentical($x, $y) | schlägt fehl, wenn $x === $y falsch ist, oder zwei Objekte ungleich oder von unterschiedlichem Typ sind |
| assertReference($x, $y) | schlägt fehl, es sei denn $x und $y sind dieselbe Variable |
| assertCopy($x, $y) | schlägt fehl, wenn $x und $y dieselbe Variable sind |
| assertSame($x, $y) | schlägt fehl, es sei denn $x und $y sind dieselben Objekte |
| assertClone($x, $y) | schlägt fehl, es sei denn $x und $y sind identisch, aber nicht dieselben Objekte |
| assertPattern($p, $x) | schlägt fehl, es sei denn der reguläre Ausdruck $p matched $x |
| assertNoPattern($p, $x) | schlägt fehl, wenn denn der reguläre Ausdruck $p matched $x |
| expectError($e) | schlägt fehl, wenn der Fehler $e nicht vor Ende dieses Tests eintritt |
| expectException($e) | schlägt fehl, wenn die Exception $e nicht vor Ende dieses Tests geworfen wird |
TODO (mlunzena) fehlt noch
TODO (mlunzena) Hier fehlen noch ein paar weitere Links.
Letzte Änderung am 29.03.2010 15:19 Uhr von mriehe.
Hier finden Sie Entwickler-Dokumentation für Stud.IP.
Hilfe zur Bedienung und Administration von Stud.IP finden Sie im Dokumentations-Portal.