Einführungin das automatisierte Layout Testing

Layout Tests waren schon immer wichtig, gewinnen aber zunehmend an Bedeutung. Warum das so ist und wie ihr euer Layout automatisiert testen könnt, erkläre ich in diesem Artikel.

Mehr oder weniger gründliche Layout Tests haben wir schon immer gemacht. Schließlich sollen unschöne Fehler vor dem Start einer Webseite und nicht erst durch den Kunden gefunden werden. Trotzdem beschränken sich diese meist nur auf sporadische, manuelle Vorgehensweisen. Heutige Webseiten werden aufgrund von gestiegenen Anforderungen an Größe und Responsivität immer komplexer. Daher werden automatisierte Layout Tests, insbesondere für große Webseiten, immer interessanter. Im folgenden Artikel möchte ich einen grundlegenden Überblick über die verschiedenen Arten von automatisierten Layout Tests sowie erste Beispiele vorstellen.

Auswahl der Methodik

Grob lassen sich drei Methoden der Testautomatisierung unterscheiden. In Spezifikationstests werden Layouts anhand vorher definierter Regeln geprüft. Dies bedeutet, dass das Aussehen einer Webseite in einer eigenen Syntax separat definiert werden muss, was natürlich einen deutlichen Mehraufwand erzeugt. Eine Alternative zu den sehr umfangreichen Spezifikationstests sind der Cross-Browser bzw. der Regressionstest. Bei ersterem werden Layoutunterschiede einer Webseite zwischen verschiedenen Browsern automatisiert untersucht. Beim Regressionstest werden verschiedene Versionen einer Webseite auf Unterschiede getestet.

Zum automatisierten Testing gehört im weitesten Sinne auch das Testen auf fehlerfreie Syntax, z.B. mittels einer geeigneten IDE und das Testen auf Einhaltung von Standards. Der Github-Editor Atom ist sicher nicht nur diesbezüglich eine Empfehlung wert.

Im Folgenden möchte ich das Framework BackstopJS vorstellen, das für einfache Regressionstests gut geeignet ist. Als weiteres werde ich das Galen Framework vorstellen, das nicht nur spezifikationsbasiert arbeitet, sondern auch Regressionstests, Cross-Browser-Tests und sogar funktionale Tests ermöglicht.

BackstopJS

Immer wieder machen wir Änderungen und stellen nicht fest, dass diese auch Teile unseres Layouts betreffen, welche wir gar nicht beabsichtigt haben zu ändern. Daher schauen wir uns BacktopJS an, einen der bekannteren CSS-Regressionstests basierend auf JavaScript.

Zunächst einmal wird node.js vorausgesetzt. Nach erfolgreicher Installation auf eurem System wechseln wir in unser Projektverzeichnis (als Beispiel verwende ich das Bootstrap Projekt Cover), indem unser Webprojekt liegt und installieren BacktopJS mit dem node.js Paketmanager npm:

cd /path/to/project
npm install --save-dev backstopjs

Danach müssen wir unsere Konfigurationsdateien erstellen lassen. Dazu wechseln wir in das Verzeichnis node_modules/backtopjs und führen den Befehl npm run genConfig aus.

Unser Verzeichnis sollte nun wie folgt aussehen:

Verzeichnis BacktopJS

In der Datei backtop.json finden wir die zentrale Konfigurationsdatei. Wir überschreiben die Demokonfiguration mit folgender:

{
  "viewports": [
    {
      "name": "phone",
      "width": 320,
      "height": 480
    },
    {
      "name": "tablet_v",
      "width": 568,
      "height": 1024
    },
    {
      "name": "tablet_h",
      "width": 1024,
      "height": 768
  },
  {
    "name": "desktop",
    "width": 1920,
    "height": 1080
  }
  ],
  "scenarios": [
    {
      "label": "My Test Page",
      "url": "../../index.html",
      "hideSelectors": [],
      "removeSelectors": [
      ],
      "selectors": [
        ".masthead",
        ".inner.cover",
        ".mastfoot"
      ],
      "readyEvent": null,
      "delay": 500,
      "misMatchThreshold" : 0.1,
      "onBeforeScript": "onBefore.js",
      "onReadyScript": "onReady.js"
    }
  ],
  "paths": {
    "bitmaps_reference": "../../backstop_data/bitmaps_reference",
    "bitmaps_test": "../../backstop_data/bitmaps_test",
    "compare_data": "../../backstop_data/bitmaps_test/compare.json",
    "casper_scripts": "../../backstop_data/casper_scripts"
  },
  "engine": "phantomjs",
  "report": ["CLI", "browser"],
  "casperFlags": [],
  "debug": false,
  "port": 3001
}

Dort legen wir unter viewports die zu testenden Displaygrößen fest: phone, tablet_v, tablet_h und desktop. Unter scenarios legen wir die einzelnen Bereiche einer Webseite fest, die getestet werden sollen. Wir testen hier beispielsweise die Navigation, das Cover und die Fußleiste. Das ergibt 12 Testfälle (3 Testbereiche x 4 Viewports). Unter path werden die Pfade der Screenshots festgelegt.

Nun können wir unsere Referenzbilder mit dem Befehl npm run reference erstellen. Diese befinden sich dann unter backstop_data/bitmaps_reference.

Wir können unseren ersten Test starten: npm run test. Dieser vergleicht nun die Referenzbilder mit unserer jetzigen Version unserer Webseite. Da wir noch keine Änderung vorgenommen haben, sollten alle Tests natürlich erfolgreich sein:

Unter backstop_data/bitmaps_test findet ihr nun eure Testbilder, die für diesen Testdurchlauf erzeugt wurden und mit den Referenzbildern verglichen wurden. Unter http://localhost:3001/compare/ erzeugt BacktopJS euch einen schönen, übersichtlichen Report zu dem Testdurchlauf.

Machen wir unsere ersten Änderungen und ändern den Innenabstand von Listenpunkten:

<style>
    li {
        padding: 5px;
    }
</style>

Nach erneutem Ausführen npm run test erhalten wir nun ein aktuelles Testergebnis:

Test completed...
   8 Passed
   4 Failed

Diesmal fallen alle 4 Viewportgrößen im Navigationstestfall durch. Im Report werden alle Testfälle mit Referenzbild, aktuellem Testbild und Differenzbild angezeigt. In unserem Beispiel haben sich die Navigationspunkte verschoben.

BacktopJS Diff

Ihr seht, BacktopJS ist einfach zu bedienen, Testfälle sind einfach zu erstellen. Das oben gezeigte Beispiel ist trivial, doch bei großen Projekten können Regressionstests einen enormen Vorteil bringen um unbeabsichtigt veränderte Teile einer Webseite zu entdecken.

Weitere Informationen zu BacktopJS gibt es auch auf dem Blog des Entwicklers Garris Shipon.

Galen Framework

Das Open-Source Framework Galen ist eine analytische Methode, um das Look and Feel einer responsiven Webseite zu testen und daher insbesondere für Testgetriebene Entwicklung (TDD) geeignet. In einer Spezifikationsdatei werden Angaben über das Layout in der Galen Spec Language definiert. Diese ist durchaus intuitiv und lässt sich auch ohne Vorkenntnisse gut verstehen. Galen kann dabei verschiedene mitgelieferte Viewports berücksichtigen. Eigene Viewports lassen sich problemlos definieren. Mittels Selenium Grid lassen sich die Tests automatisiert auf verschiedenen Systemen und Browsern testen. Darüber hinaus unterstützt Galen Bildvergleiche (sprich Regressionstests) und sogar funktionale Tests.

Selenium ist eine Testumgebung, basierend auf HTML und Javascript, um Webanwendungen auf ihre Funktionalität hin in verschiedenen Browsern zu testen. Beispielsweise lässt sich das Verhalten von Webformularen überprüfen. Selenium Grid ist eine Erweiterung von Selenium, mit der es möglich ist, Tests parallel auf verschiedenen Servern auszuführen, um die Dauer der Testdurchführung zu verkürzen und eine stärkere Anzahl an Systemen und Browsern zu berücksichtigen.

Galen lässt sich per npm installieren:

sudo npm install -g galenframework-cli

Oder ihr ladet euch Galen herunter und installiert es mit folgendem Befehl:

sudo ./install.sh

Ob Galen einwandfrei funktioniert könnt ihr mit folgendem Befehl testen:

galen -v

Zunächst definieren wir unser Layout in der Galen Spec Language, wir nennen die Datei homepage.gspec:

@objects

    header		   css   div.masthead
    brand		   css   h3.masthead-brand

= Header =

    @on all
      brand: 
        inside header 40px top

    @on mobile
      brand:
         centered horizontally inside header

Im ersten Teil definieren wir unsere Objekte, mit denen wir später arbeiten möchten. Dazu weisen wir diesem in der ersten Spalte einen Namen zu, in der zweiten legen wir die Auswahlmethode fest (zur Auswahl stehen id, css oder xpath) und in der dritten Spalte wählen wir unser Objekt aus. In unserem Beispiel mittels CSS-Selektoren.

Im Folgenden definieren wir eine Sektion, die wir Header nennen und in zwei Gleichheitszeichen einschließen. Sektionen dienen im wesentlichen dazu, unsere Regeln zu strukturieren. Mit dem Schlüsselwort @on, gefolgt von einem Viewport, leiten wir eine Testsequenz für eine bestimmte Bildschirmgröße ein.

Wichtig: zum Einrücken müssen 1 bis 8 Leerzeichen genutzt werden. Tabs werden ignoriert!

Es sind verschiedenste einfache Regeln nutzbar wie near, width, inside und height. Eine Übersicht über aller verfügbaren Regeln gibt es hier.

In unserem kleinen Beispiel soll der obere Außenabstand des Logos genau 40 Pixel betragen. Außerdem soll das Logo in der mobilen Ansicht im Header zentriert werden.

Neben diesen einfachen Regeln zur Beschreibung von Objekten einer Webseite, werden in der Galen Extra Library weitere Regeln definiert, welche die Galen Spec Language mit vielen komplexeren Ausdrücken erweitern.

Als Zweites kommt nun die Galen Test Suit Syntax zum Einsatz. In dieser werden Testsequenzen definiert. Außerdem lassen sich hier auch Einstellungen (wie etwa die Viewportgrößen) definieren. Wir legen uns unter testsuit.test eine kleine Testsuit an:

Homepage on a small mobile device
    http://localhost/index.html 320x600
        check   homepage.gspec --include "mobile,all"

Homepage on a tablet device
    http://localhost/index.html 640x480
        check   homepage.gspec --include "tablet,all"

Homepage on a desktop device
    http://localhost/index.html 1024x800
        check   homepage.gspec --include "desktop,all"

Wir definieren uns hier drei Testdurchläufe. In allen diesen drei Testdurchläufen wird unsere zuvor erstellte Testdatei als Quelle unserer Regeln angegeben.  Geprüft wird hier jeweils auf anderen Viewportgrößen. Hier könnten wir nun auch verschiedene Browsertests definieren (auch über die Cloud, mittels Seledium Grid) und vieles mehr. Wir starten nun unseren Test:

galen test testsuit.test --htmlreport .

Wir geben zum einen den Pfad zur Testsuit an, zum anderen, dass Galen uns einen HTML-Report erstellen soll. Während der Test durchläuft, öffnet sich immer wieder der Browser in den verschiedenen Bildschirmgrößen. Unser Testfälle sind schließlich erfolgreich:

========================================
Test: Homepage on a small mobile device
========================================
check   homepage.gspec --include "mobile,all"
= Header =
    brand:
        inside header 40px top
        centered horizontally inside header

========================================
Test: Homepage on a tablet device
========================================
check   homepage.gspec --include "tablet,all"
= Header =
    brand:
        inside header 40px top

========================================
Test: Homepage on a desktop device
========================================
check   homepage.gspec --include "desktop,all"
= Header =
    brand:
        inside header 40px top


========================================
----------------------------------------
========================================
Suite status: PASS
Total tests: 3
Total failed tests: 0
Total failures: 0

Unser HTML-Report sieht wie folgt aus:

Um einen Fehler zu provozieren ändere ich den Außenabstand des Headers zur oberen Bildschirmkante auf 20px:

    @on all
      brand:
        inside header 20px top

Nach erneutem Testdurchlauf erhalten wir Fehlermeldungen:

Mit Klick auf die Tests können wir uns den Fehler genauer anschauen:

Das Schöne an Galen ist auch, dass von der betroffenen Stelle auf der Webseite eine Heatmap erstellt wird:

Dieses Beispiel sollte lediglich als Einführung in ein eigenes komplexes Thema dienen. Wer sich tiefer in das sehr mächtige Framework einlesen möchte, dem sei der Artikel des Galen Entwicklers Ivan Shubin auf Smashing Magazine empfohlen. Auch eine zehnteilige Videoreihe von ihm ist auf Youtube verfügbar.

Fazit

Die Komplexität von Webseiten steigt, durch moderne Testwerkzeuge lässt sich das automatisierte Testen aber immer komfortabler und schneller realisieren. In welchem Fall das trotzdem noch recht aufwendige Testen gerechtfertigt ist, muss von Fall zu Fall entschieden werden. Meines Erachtens macht es nur bei sehr komplexen und langlebigen Projekten Sinn. Projekte, bei denen hohe Qualität und Konsistenz an erster Stelle stehen.


Über den Autor

Hallo! Ich bin Robin Cramer und entwickle Webseiten. Was wäre das Internet ohne gegenseitige Hilfe? Aus diesem Grund veröffentliche auch ich in unregelmäßigen Abständen zu allem was mit der Entwicklung von Webseiten zu tun hat.


Webseite

Hinterlassen Sie einen Kommentar

Ihre E-Mail-Adresse wird nicht veröffentlicht.