Skip to content

Snapshot-Testing für PHP-gerenderte Views

Vor kurzem habe ich den Artikel What Is Snapshot Testing, and Is It Viable in PHP? von Christopher Pitt gelesen. Von Snapshot Testing hatte ich bis dahin noch nie gehört. Unter anderem fand ich interessant, wie er das Rendering von Templates testet.

It’s clear what the template should produce, given repeatable initial information. We could even mock the initial data, and assert the output.

Er nimmt einen kleinen HTML-Schnipsel, in den einige PHP-Variablen eingesetzt werden, befüllt diese einmal mit definierten Werten, und lässt einen Snapshot davon erstellen. Beim nächsten Testlauf lässt sich der Output mit diesem Snapshot vergleichen. Haben sich der HTML-Code oder die Werte aus welchen Gründen auch immer geändert, schlägt der Test fehl.

Mit spatie/phpunit-snapshot-assertions gibt es eine Bibliothek, die Snapshot-Testing mit PHPUnit bzw. Codeception möglich macht. Da ich gerade einige Codeception-Tests für ein älteres Zend Framework 1-Projekt geschrieben habe, das ich teilweise refactoren wollte, kam mir die Lib gerade recht.

"Snapshot-Testing für PHP-gerenderte Views" vollständig lesen

Tester's Little Helpers

Gestern Abend habe ich im Rahmen des Treffens der PHP User Group Rheinhessen einige Tools, Helferlein und ausgewachsene Frameworks vorgestellt, die Entwickler beim Schreiben von Tests unterstützen können. In den vergangenen Monaten sind nämlich einige in meiner Bookmark-Liste gelandet. Viele dieser Tools sind opinionated, also eigensinnig, was durchaus kontroverse Meinungen in unserer Runde herausforderte.

Wir tauschten uns auch über Best Practices im Bereich Testing aus: Wie wichtig ist eine hohe Code Coverage? Sollten Test Cases im selben Namespace liegen wie die zu testenden Objekte? Wie gehen wir mit Testdaten in Datenbanken um? Sollte unter verschiedenen PHP-Versionen getestet werden (z.B. bei TravisCI)? Ich glaube, jeder konnte etwas vom gestrigen Abend für sich mit nach Hause bzw. mit ins Projekt nehmen.

Weil ich meine Slides relativ kurzfristig zusammengestellt habe, möchte ich sie hier (noch) nicht veröffentlichen. Die von mir gesammelten Tools will ich aber niemandem vorenthalten:

"Tester's Little Helpers" vollständig lesen

PHPUnit für die Entwicklung von Serendipity-Plugins

Geben wir es ruhig zu, der PHP-Code von Serendipity ist nicht mehr State of the Art, sondern zum großen Teil noch auf dem Stand von PHP 4. Dass dieser Code immer noch sehr zuverlässig funktioniert, und ob und wie mit dem aktuellen Stand umzugehen ist, soll hier nicht das Thema sein. Ich möchte hier auf die Entwicklung von Serendipity-Plugins eingehen, die nicht umsonst in einem eigenen Repository leben. Deren Qualität lässt sich mithilfe von Unit Tests sicherstellen.

PHPUnit für Plugins

Auch wenn die Grundfunktionalität von Serendipity durch Unit Tests abgedeckt ist: Die Plugin-Entwicklung ist bisher nicht so einfach zu testen. In meinen letzten Projekten waren Unit Tests mit PHPUnit ein zunehmend zentraler Bestandteil der Entwicklung. Entweder damit ich nachträglich sicherstellen konnte, dass Klassen und Methoden bei Veränderungen und Refactoring noch taten, was sie tun sollten; oder weil ich testgetrieben entwickelte, das heißt zuerst die Unit Tests und dann erst den zu testenden Code schrieb. Dieses Vorgehen möchte ich nicht mehr missen, und es hat mich gestört, dass es bei der Entwicklung von Serendipity-Plugins nicht ohne Weiteres möglich war.

Screenshot einer Konsole mit erfolgreich durchlaufenen Unit Tests

Daher habe ich mich hingesetzt und PHPUnit so in meine lokale Serendipity-Installation, die ich zum Entwickeln verwende, integriert, dass ich einzelne (Event-)Plugins separat testen kann. Die spezifischen Herausforderungen ließen sich recht schnell überwinden:

  • In Serendipity werden Plugins stark getrennt vom Core über Event-Hooks ausgeführt. Diese Hooks müssen natürlich einzeln getestet werden können.
  • Viele Variablen sind als global deklariert oder werden per Referenz "herumgereicht". Das erfordert einige Workarounds, die heute dank Dependency Injection und ähnlichen Entwurfsmustern zum Glück überflüssig sind.
  • Data Fixtures: Um Serendipity für die Tests "hochzufahren", wird eine Datenbankverbindung benötigt. Mir ist es bisher nicht gelungen, eine der unter Database Testing aufgeführten Methoden umzusetzen. Besser gesagt: Ich war einfach zu faul und habe die nötigen Daten in einer SQLite-Datenbank hinterlegt.
"PHPUnit für die Entwicklung von Serendipity-Plugins" vollständig lesen

Selenium Tests mit NetBeans und PHP

Selenium-Tests können elegant direkt in NetBeans für PHP erstellt und aus NetBeans heraus ausgeführt werden. Leider funktioniert das unter bestimmten Umständen nicht out-of-the-box, sondern macht einige Kniffe notwendig.

NetBeans-Plugin installieren

Ich gehe davon aus, dass ihr alles notwendige für die PHP-Entwicklung installiert habt. Das schließt PHPUnit ein, auf das die Selenium-Tests zurückgreifen. Wie man Selenium in PHPUnit integriert, wird hier ausführlich beschrieben.

Auf meinem Ubuntu-Rechner mit NetBeans 6.9.1 und Firefox 3.6.12 lässt sich das Selenium Module for PHP aus dem NetBeans Beta-Repository einfach installieren: Unter "Extras > Plugins > Einstellungen" das Häkchen bei "NetBeans Beta" setzen, dann steht das Selenium-Modul zur Auswahl und kann installiert werden. Anschließend lässt sich nach Rechtsklick auf das Projekt im Projektmanager der Punkt "Run Selenium Tests" aus dem Kontextmenü auswählen. Zunächst muss ein Verzeichnis ausgewählt werden, in dem die Testdateien abgelegt werden. Ich habe den Ordner selenium direkt neben nbprojects in meinem Projektverzeichnis angelegt und als Testverzeichnis ausgewählt.

Da wir noch keine Testdateien erstellt haben, wird auch noch nichts ausgeführt, aber das Verzeichnis wird als Selenium Test Files aufgeführt. Wiederum über das "Kontextmenü > Neu" kann jetzt ein "Selenium Test Case for PHP" erstellt werden. Dabei legt NetBeans freundlicherweise schon das Code-Gerüst für den neuen Test-Case an. Natürlich kann, wer möchte, auch manuell Test-Cases im Test-Verzeichnis anlegen oder den PHP-Code aus der Selenium IDE (= Firefox-Extension) herausgenerieren lassen. Die NetBeans-Vorlage sieht etwa wie folgt aus.

require_once 'PHPUnit/Extensions/SeleniumTestCase.php';

class newSeleneseTest extends PHPUnit_Extensions_SeleniumTestCase
{
    protected function setUp()
    {
        $this->setBrowser("*chrome");
        $this->setBrowserUrl("http://change-this-to-the-site-you-are-testing/");
    }

    public function testMyTestCase()
    {
        
    }
}

Unabhängig davon, welchen Test man in testMyTestCase() implementieren möchte, gilt es jetzt noch einige Stolpersteine aus dem Weg zu räumen.

"Selenium Tests mit NetBeans und PHP" vollständig lesen