PHP: Funktionstests auf Bilder mit Codeception

In einem Symfony-Projekt soll mit Codeception ein Funktionstest erstellt werden, der die Webseite auf nicht geladene Bilder untersucht. Weiterhin soll die Funktionalität natürlich nicht nur in einem einzelnen Test, sonder über die gesamte Suite und ggfs. in weiteren Testsuites verfügbar sein.

Also muss man sich einen eigenen Helper erstellen. Darin kann man aus dem bestehenden Set des PhpBrowser oder Selenium Moduls die benötigte Funktionalität zusammenbauen und so dem gesamten Projekt zu Verfügung stellen, ganz nach Anforderung.

Vorbereitung: Der eigene Helper

Zunächst einmal benötigt man einen eigenen Helper. Diesen legt man im Ordner _support/Helper/ an, in meinem Beispiel heisst dieser Helper „myHelper.php“.

<?php
namespace Helper;

// here you can define custom actions
// all public methods declared in helper class will be available in $I

class myHelper extends \Codeception\Module {

}

Anschliessend muss der Helper noch der Testsuite bekannt gemacht werden. Dafür reicht folgender Eintrag bei den aktivierten Modulen der Testsuite.

modules:
    enabled:
        - \Helper\myHelper

Ansatz 1: Ist das gewünschte Bild sichtbar?

Die einfachste Prüfung lässt sich mit XPath und der seeElement Funktion erledigen. seeElement prüft ob ein Element im DOM vorhanden und sichtbar ist. Die nachfolgende Funktion erwartet die URL der Grafik, ruft den PhpBrowser auf und prüft das Bild.

    public function seeImagewithSource($imageUrl) {
        $phpBrowser = $this->getModule('PhpBrowser');
        $phpBrowser->seeElement('//img[@src="'.$imageUrl.'"]');
    }

Diese Variante deckt jedoch nicht alle Grafiken ab. Man müsste für einen Test jedes Bild kennen und angeben. Das kann sich bei redaktionell gepflegten Seiten als schwierig herausstellen.

Ansatz 2: Prüfung mit Selenium

Das nächste was mir einfiel war alle Bilder per JavaScript zu prüfen. Der folgende Script loopt über alle Bilder und prüft die Darstellung.

Array.prototype.slice.call(document.images).every(function (img) {return img.complete && img.naturalWidth > 0;});

Kann ein Bild nicht geladen oder dargestellt werden, liefert das Script false zurück. In Codeception lässt sich das mit dem Modul Selenium prüfen.

function checkAllImages() {
        $result = $this->getModule('Selenium2')->session->evaluateScript("return (function(){ return Array.prototype.slice.call(document.images).every(function (img) {return img.complete && img.naturalWidth > 0;}); })()");
        return $result;
}

Solange die Bilder direkt verfügbar sind ist das eine annehmbare Lösung. Werden die Bilder jedoch von extern geladen, kann es zu Zeitverzögerungen kommen und somit würde der Test unter Umständen fehlschlagen – das Bild wäre aber vorhanden.

Ansatz 3: Prüfen des Statuscodes

Die Zeitverzögerung hat mich dann zum nächsten Ansatz geführt: Die Überprüfen aller Bilder einer Seite auf ihren Statuscode. Der zurückgelieferte Code 200 heisst „OK“, das Bild kann geladen werden. Alle anderen Codes lassen den Test fehlschlagen.

Hierfür nutzt man wieder den PHPBrowser. Mit grabMultiple holt man sich alle Bilder und loopt über das Ergebnis. Mit amOnPage prüft man die Grafik, seeResponseCodeIs liefert den gewünschten Statuscode zurück. Mit diesem Test lassen sich alle Grafiken auf einer Seite prüfen.

    public function checkAllImagesSource() {
        $phpBrowser = $this->getModule('PhpBrowser');
        $results = $phpBrowser->grabMultiple('img', 'src');
        foreach($results as $result) {
            \Codeception\Util\Debug::debug($result);
            $phpBrowser->amOnPage($result);
            $phpBrowser->seeResponseCodeIs(200);
        }
    }

 


Beitrag veröffentlicht

in

von

Schlagwörter: