Wer mit PHP Test-driven oder Behavior-driven arbeitet und sich an Rubys Rspec und Cucumber orientiert, hat sicher schon eine Rspec-analoge Syntax für PHP vermisst. Das BDD Framework PhpSpec soll diese Lücke schließen.
Warum reicht uns denn PHPUnit nicht aus? BDD und TDD heißt outside in – vom Verständnis der Domain und den Anforderungen der Domain hin zum Code. Wir formulieren Erwartungen an das Verhalten von Code (should), der erst noch entstehen muss und wollen nicht nur testen, ob bestehender Code korrekte Ergebnisse liefert (assert). Aber es geht um mehr, als nur die Wortwahl, es geht um die Grundhaltung, den Code von den Anforderungen her zu modelieren.
Dem Blog-Artikel liegt diese Version zu Grunde:
phpspec version 2.0.1-PREVIEW
Lead Developer ist Marcello Duarte.
Dokumentation und Infos gibt es unter: http://www.phpspec.net
Ich will hier mit einer kurzen Anleitung zur Installation und einem Beispiel Interesse wecken für PhpSpec.
Installation
Mit Composer ist PhpSpec schnell installiert. Dazu im Wurzelverzeichnis des Projektordners eine composer.json anlegen und mit folgendem Inhalt füllen, anschließend ein composer install ausführen.
{ "require": { "phpspec/phpspec":"dev-master" }, "config": { "bin-dir": "bin" }, "autoload": {"psr-0": {"": "src"}} }
Jetzt haben wir ein vendor Verzeichnis mit allen Abhängigkeiten und ein bin Verzeichnis mit einer ausführbaren Datei phpspec, die den Autoloader einbindet und die Tests laufen lässt. Der Aufruf von bin/phpspec sagt uns jetzt aber noch nicht mehr, als dass es noch keine Tests gibt.
Ein erster Test mit PhpSpec
Mit PhpSpec lassen sich die Test- und Code-Schritte sehr flüssig von der Command Line aus erzeugen, ein minimales Scaffolding nimmt uns das Erstellen von Test-Klassen und Klassen ab.
Schauen wir uns das einfach in einem Beispiel an. Wir wollen in einer Schule Kurse anbieten, dazu brauchen wir unter anderem ein Objekt Teacher. Wir machen folgenden Aufruf auf der Commandozeile:
bin/phpspec describe Teacher
Wir bekommen die folgende Rückmeldung:
Ein Spec-File, der Namespace, Abhängigkeiten und die Deklaration der Testklasse bereits enthält, wird im Verzeichnis spec abgelegt:
Einen ersten Test bekommen wir auch gleich mitgeliefert, er überprüft, ob es die Klasse Teacher gibt. Schauen wir, was unser Testrunner daraus macht.
Die Testmethode it_is_initializable() schlägt wie erwartet fehl und wir werden gefragt, ob wir die Klasse Teacher erzeugen möchten. Ja, möchten wir, quittieren mit ‚y‘ und bekommen im Verzeichnis src einen File Teacher.php abgelegt, der die gewünschte Klasse enthält.
Unser Test läuft jetzt durch und wir erstellen gleich den nächsten Test:
Unser Teacher soll einen Namen haben, den wir hier in äußerster Einfachheit mit der Methode getName() erfragen.
Lassen wir unsere Tests wieder laufen.
Ja, gerne lassen wir uns von PhpSpec die Arbeit abnehmen. Wer mit behat arbeitet, kennt die Signaturen und leeren Methodenrümpfe, die wir jetzt in unserer Klasse finden.
Wir geben hier das erwartete Return-Value ein und starten die Tests erneut.
Mach es schöner
Inzwischen habe ich noch ein paar Klassen für meinen Kursplaner angelegt (Pupil, SchoolClass). Die Tests laufen durch, aber schön wären noch ein paar mehr Infos zu den Tests. Das können wir mit dem Parameter
bin/phpspec --format=pretty
erreichen und für die Zukunft in einer phpspec.yml im Wurzelverzeichnis mit dieser Zeile einkonfigurieren:
formatter.name: pretty
Fehlschlagende Tests werden entsprechend markiert:
Beispiele für Matcher, Hooks,Mocks, Stubs findet man im Manual unter
http://www.phpspec.net/docs/introduction.html
http://www.phpspec.net/cookbook/matchers.html
Ein Blick in das vendor-Verzeichnis vendor/phpspec/phpspec/spec lohnt sich, hier ist ein Pool von konkreten Testbeispielen.
Hilf mir
Die für bin-phpspec verfügbaren Parameter bekommen wir mit
bin/phpspec -h
Die verfügbaren Commands fördert das Command list zutage
bin/phpspec list
Will man nur einzelne Tests laufen lassen, ruft man das Command run auf, gefolgt vom auszuführenden Verzeichniss oder der gewünschten Datei.
bin/phpspec run spec/Teacher.php
Fazit
Wer mit RSpec oder Jasmine arbeitet, wird mit der Syntax noch nicht ganz glücklich sein und die verschachtelten describe Strukturen vermissen. Über den Ansatz, die Signaturen der Testmetoden mit einem Unterstrich zu separieren und dann als Testbeschreibung auszugeben, kann man streiten. Aber die Richtung stimmt. Wer mit PHP testgetrieben arbeiten möchte, hat die Möglichkeit, mit behat und phpspec schnell ein Grundgerüst aufzusetzen und einen robusten Code über die Abbildung von Domain Wissen und das Modelieren von Anforderungen voranzutreiben.
Schreibe einen Kommentar