Test-driven Development mit PHP macht Laune

Bei einem neuen Projekt, welches ich mit dem Zend Framework entwickel, habe ich bisher von Beginn an konsequent den Ansatz der testgetriebenen Entwicklung (neudeutsch test-driven development, kurz TDD) verfolgt. Das bedeutet, dass ich keine einzige Zeile Programmcode für meine Applikation ohne dazugehörigen Tests schreibe. Bisher habe ich das auch komplett durchgehalten, so dass die Anwendung derzeit zu 100% durch Unit Tests und Web Tests abgesichert ist.

Ansatz der testgetriebenen Entwicklung (TDD)

Der Ansatz der testgetriebenen Entwicklung ist im wesentlich ganz einfach. Es gibt drei Schritte, die laufend wiederholt werden. Die ersten beiden Schritte werden eigentlich ständig wiederholt, während der dritte nur bei Bedarf durchgeführt wird.

  1. Schreibe einen Test, der zunächst fehlschlägt
  2. Schreibe nur soviel Code, dass der Test erfolgreich durchläuft
  3. Refaktoriere deinen Code, wobei alle Tests weiterhin erfolgreich durchlaufen sollen

Man muss sich dabei schon stark umstellen, da man ständig zwischen seinen Tests und dem Applikationscode hin und her springen muss. Auch ist es eher ungewohnt, einen Test für eine Klasse oder Methode zu schreiben, die noch gar nicht existiert. Nach einer Eingwöhnungsphase lernt man aber nach und nach, seinen Programmierstil schrittweise umzustellen.

Die Entwicklungszeit dauert subjektiv erst einmal viel länger, weil man ja nicht nur seinen Applikationscode, sondern auch den Testcode programmieren muss. Dafür lassen sich aber Bugs schneller finden, wenn man an zentraler Stelle eine Änderung durchführt, die auch nicht vorhersehbare Auswirkungen auf andere Programmteile hat. Wenn ich z.B. das Zend Framework mit einem “nightly snapshot” aktualisiere, lasse ich einfach all meine Tests laufen und kann effektiv alle neuen Probleme finden. Das wilde Herumprobieren, das selten vollständig ist, wird auf Anhieb sicher niemals alle Probleme finden, die durch die Aktualisierung des Frameworks mitunter auftreten könnten.

Tools für die testgetriebene Entwicklung in PHP

Ich verwende derzeit zwei Tools für die testgetriebene Entwicklung in PHP. Eines für die Erstellung von Unit Tests und eines für die Erstellung von Web Tests. Was ein Unit Test ist, sollte klar sein, unter einem Web Test verstehe ich den Test einer Website.

Für meine Unit Tests verwende ich PHPUnit von Sebastian Bergmann. Sebastian hat das PHPUnit Handbuch dafür kostenlos auf seiner Website bereit gestellt. So bleiben kaum Fragen offen. Mit PHPUnit teste ich beliebige Klassen für Model und Controller, Framework Klassen, Routen sowie Funktionssammlungen.

Für meine Web Tests wiederum verwende ich den Webtester von Simpletest von Marcus Baker. Auch Simpletest ist sehr gut dokumentiert. Mit dem Simpletest Webtester teste ich die Navigation und die grundlegende Seitenstruktur der Website sowie vor allem die Verwendung von Formularen. Mit Hilfe des Webtesters simuliere ich Clicks auf Links, frage Cookies und Response Codes ab, befülle Formularfelder mit Daten und sende Formulare ab.

Fazit

Ich könnte noch einiges mehr zum Thema schreiben, nur leider lässt dies meine Zeit momentan nicht zu. Ich war halt nur so begeistert, dass ein Update des Zend Frameworks in kurzer Zeit erledigt ist und meine Anwendung weitestgehend fehlerfrei läuft.

Der Ansatz der testgetriebenen Entwicklung ist sicher nicht Jedermanns Sache. Wenn man aber die Einstiegshürden überwunden und die Umgewöhnungsphase überstanden hat, lernt man recht schnell, dass dieser Weg sehr effektiv und auf lange Sicht zeitsparender als der Trial-and-Error Ansatz.

8 Antworten für “Test-driven Development mit PHP macht Laune”

  1. Thomas Peterson sagt:

    Hallo,

    Könntest du die Test für das Blog auch online stellen? Ich würde die mir gerne mal anschauen.

    Und ich möchte dir noch mal zu den Guten Artikeln gratulieren.

  2. Ralf Eggert sagt:

    Hallo Thomas,

    also die Tests gehören nicht zu dem Blog, das im Tutorial erstellt wird, sondern zu einem internen Projekt, an dem ich gerade entwickel.

    Ein guter Einstieg sind aber die Tests zum Zend Framework selber. Da kann man schon einmal gut sehen, wie man seine Tests prinzipiell aufbauen und organisieren kann. Lade dir einfach mal einen aktuellen Snapshot herunter und schaue dort ins Verzeichnis /tests

    http://framework.zend.com/download/snapshot

    So ähnlich habe ich dann auch angefangen.

    Gruß,

    Ralf

  3. Thomas Weidner sagt:

    Ralf,

    warum verwendest Du nicht [Selenium| http://www.phpunit.de/pocket_guide/3.0/en/selenium.html wie es auch in der Doku von PHPUnit empfohlen wird. Gibt ne eigene Extension dafür.

    Ausserdem kannst Du mit Selenium auch JS testen was mit SimpleTest laut Doku nicht geht (zumindest hab ich auf die Schnelle nix gefunden).

    Grüße
    Thomas (Zend I18N TeamLeader)

  4. Ralf Eggert sagt:

    Hallo Thomas,

    gute Frage. Ich hatte mir das angeschaut, aber es gefiel mir nicht wirklich. Zum einen muss mit Selenium ein weiterer Prozess laufen, damit es funktioniert. Dann wurde bei jeder Ausführung des Tests ein neues Browserfenster gestartet und danach nicht geschlossen (wird ein Bug sein, kann also schon erledigt sein). Der Overhead beim Laden eines neuen Browserfensters bleibt aber dennoch bestehen. Die Tests laufen mit Simpletests Webtester einfach viel schneller als wenn ich Selenium verwende.

    Dass man JS nicht testen kann, ist schon ein Manko, aber das ist bei mir derzeit nicht so wichtig.

    Gruß,

    Ralf

  5. sas171 sagt:

    Hallo Ralf,
    wieso hast Du die Kombination von PHPUnit und SimpleTest gewählt anstatt einfach SimpleTest für alles zu nutzen? So weit ich es verstehe hat SimpleTest nur Vorteile gegenüber PHPUnit.

    mfg
    sas

  6. Ralf Eggert sagt:

    Moin Sas,

    ich habe PHPUnit gewählt, weil das ZF damit auch seine Tests aufbaut. Das ist zwar nicht zwingend, aber war meine erste Wahl, auch wegen einiger Features von PHPUnit 3 (z.B. Prüfen der Testabdeckung). Da aber PHPUnit leider keine vernünftige Unterstützung für das Testen von Webseiten bereit stellt (Selenium mag ich nicht), verwende ich für die Web Tests halt Webtester. Komplett auf Simpletest umzusteigen, habe ich bisher eher aus Bequemlichkeit gescheut.

    Gruß,

    Ralf

  7. Nico Flemming sagt:

    Hallo Ralf,

    eine Frage:
    Wie testest Du Controller und Views mit PHPUnit?

    Gruß,
    Nico

  8. Terrahawk sagt:

    Hallo

    Der obige Artikel ist etwas älter aber das Problem mit dem nicht schließenden Browser @Selenium hatte ich bis vor kurzem auch. Das liegt daran das die Selenium IDE die Tests sinnfrei aufnimmt.

    Am Ende jedes Tests sollte man zusätzlich ein

    PHP:
    1. $this->stop();

    anfügen.
    Oder ggf. eine eigene Funktion :

    PHP:
    1. public function tearDown() {
    2.     $this->stop();
    3. }

    Hoffe dem nächsten hilft das weiter :)

    Gruß

Hinterlasse eine Antwort