Der folgende Beitrag stammt von einem Gastautor, Garris Shipon. Wir haben uns hier bereits mit den vier Arten von CSS-Tests beschäftigt. Regressionstests sind die schwierigsten. Dabei versucht man zu testen, ob eine Änderung, die man am CSS vorgenommen hat, zu unerwarteten visuellen Problemen geführt hat. Dies wird durch responsive Designs noch erschwert. Garris hat ein Tool dafür entwickelt, als er mit einem neuen responsiven Design für eine große Website begann. Hier führt er Sie durch den gesamten Prozess.
Dieser Artikel wurde ursprünglich im Dezember 2014 veröffentlicht. Er wurde neu geschrieben, aktualisiert und im April 2016 erneut veröffentlicht, da BackstopJS, das hier vorgestellte Haupttool, aktualisiert wurde.
Ein Anwendungsfall für visuelle Regressionstests
Machen Sie eine Suche nach „CSS Regression Testing“ und ein gemeinsames Thema wird deutlich: CSS zu brechen ist einfach, es zu testen ist schwer.
Das war der Fall zu Beginn eines responsiven CSS-Refactoring-Projekts, das ich für einen großen Online-Händler konzipiert habe. Wie viele andere Webunternehmen zu dieser Zeit, waren wir dabei, einem massiven E-Commerce-Web-App, die ursprünglich für 1024px-Desktop-Bildschirme konzipiert war, responsive Verhaltensweisen hinzuzufügen.
Ich erkannte, dass dies ein regresionsanfälliger Job sein würde. Die Nachrüstung mehrerer Breakpoint-Verhaltensweisen bedeutete, dass wir wahrscheinlich viele schwer zu findende Anzeigefehler haben würden. Ich brauchte eine Möglichkeit für unsere Ingenieure, Fehler zu automatisieren, bevor wir unser QA-Team mit Hunderten von kleinen, kniffligen Layout-Problemen überhäuften.
Wo BackstopJS ins Spiel kommt
Die Lösung, die ich wollte, musste mit Webentwicklern gut funktionieren. Das heißt, einfach lokal zu installieren, vertraute Webentwicklungs-Paradigmen zu verwenden und ein angemessenes Maß an Vertrauen zu geben, dass eine für Mobilgeräte vorgenommene Selektoraänderung nicht zu einem schwer zu findenden Fehler im Desktop-Layout führt.
Zu dieser Zeit gab es nichts, was sofort passte. Das war der Grund für die Entwicklung von BackstopJS.
BackstopJS ist eine visuelle Regressionstest-App, die CasperJS, PhantomJS und ResembleJS in einer einfach zu konfigurierenden Testmatrix über mehrere App-Zustände (URLs), DOM-Elemente und Bildschirmgrößen hinweg kapselt.
Das Folgende ist eine 15-minütige Walkthrough einer Installation und einer ersten Konfiguration von BackstopJS.
Ein Tutorial zu visuellen Regressionstests
Dieses Tutorial basiert auf einem einfachen Demo-Projekt (ZIP hier herunterladen). Es stammt direkt von der Bootstrap Beispielseite.
Erweitern Sie die einfache Demo
Entpacken Sie den Projekt-Download. Wir werden das Test-Framework direkt in dieses Beispielprojekt installieren

Hier sehen Sie, was passiert, wenn Sie myCoolProject/index.html in einem Webbrowser öffnen… Denken Sie daran, es ist responsiv. Verkleinern Sie also unbedingt das Browserfenster, um das schmalste Layout zu sehen!

BackstopJS mit NPM installieren
Gehen Sie nun in Ihr Projekt-Root (`/myCoolProject/`) und führen Sie aus
$ cd ~/path-to-myProjects/myCoolProject
$ npm install backstopjs
Ihr Verzeichnis sollte jetzt so aussehen

Installation abgeschlossen! Nun kommen wir zu einigen grundlegenden Tests...
Erstellung einer BackstopJS-Konfigurationsvorlage
Der grundlegende Konfigurationsprozess ist von hier aus unkompliziert. Zur Vereinfachung kann BackstopJS eine Konfigurationsdatei generieren, die Sie für Ihr Projekt ändern können. Führen Sie im Verzeichnis `myCoolProject/node_modules/backstopjs/` aus
$ cd ~/path-to-myProjects/myCoolProject/node_modules/backstopjs/
$ npm run genConfig
Dadurch werden Dateien in Ihrem Projekt-Root hinzugefügt: Ordner für BackstopJS-Screenshots, `backstop_data`, und eine Boilerplate-Konfigurationsdatei `backstop.json`.

In der Konfigurationsdatei legen Sie Ihre Testregeln fest. Sehen wir uns diese Datei an.
{
"viewports": [
{
"name": "phone",
"width": 320,
"height": 480
}, {
"name": "tablet_v",
"width": 568,
"height": 1024
}, {
"name": "tablet_h",
"width": 1024,
"height": 768
}
],
"scenarios": [
{
"label": "My Homepage",
"url": "http://getbootstrap.com",
"hideSelectors": [],
"removeSelectors": [
"#carbonads-container"
],
"selectors": [
"header",
"main",
"body .bs-docs-featurette:nth-of-type(1)",
"body .bs-docs-featurette:nth-of-type(2)",
"footer",
"body"
],
"readyEvent": null,
"delay": 500,
"onReadyScript": null,
"onBeforeScript": null
}
],
"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": ["browser", "CLI"],
"cliExitOnFail": false,
"debug": false,
"port": 3001
}
In dieser Konfiguration sehen Sie drei `viewports`-Objekte. Eines für Telefon, vertikales Tablet und horizontales Tablet, jeweils mit den Eigenschaften `name` und `dimensions`. Sie können beliebig viele `viewports`-Objekte hinzufügen. BackstopJS benötigt mindestens eines.
Dann haben wir `scenarios`, die die URLs und Elementselektoren enthalten, die BackstopJS testen wird. Es ist sinnvoll, jedes Szenario-Objekt als Test für eine bestimmte statische Seite oder einen globalen App-Zustand zu betrachten. Fügen Sie beliebig viele `scenarios` hinzu. BackstopJS benötigt mindestens eines.
Innerhalb jedes Szenarios befindet sich eine Liste von Selektoren. Selektoren akzeptieren Standard-CSS-Notation. Für jeden von Ihnen angegebenen Selektor macht BackstopJS einen Screenshot und testet diesen Bereich Ihres Layouts. Ihr Selektorbereich kann so klein wie ein button oder so groß wie der body Ihrer Seite sein – lesen Sie die Dokumentation für weitere Informationen zur Verwendung dieser Funktion mit dynamischen Webanwendungen.
Bearbeiten der Konfigurationsvorlage
Für unsere Demo, nehmen Sie die folgende Änderung vor und ersetzen Sie den `scenarios`-Knoten in `myCoolProject/backstop.json`.
"scenarios": [
{
"label": "My Local Test",
"url": "../../index.html",
"hideSelectors": [],
"removeSelectors": [
],
"selectors": [
"nav",
".jumbotron",
"body .col-md-4:nth-of-type(1)",
"body .col-md-4:nth-of-type(2)",
"body .col-md-4:nth-of-type(3)",
"footer"
],
"readyEvent": null,
"delay": 0,
"onReadyScript": null,
"onBeforeScript": null
}
],
Referenz-Screenshots erstellen
Führen Sie im Verzeichnis `myCoolProject/node_modules/backstopjs/` aus...
$ npm run reference
Diese Aufgabe erstellt (oder aktualisiert eine bestehende) Bildschirmaufnahme, die alle angegebenen Selektoren bei jedem Breakpoint darstellt. Wenn der Prozess abgeschlossen ist, schauen Sie unter `/myCoolProject/backstop_data/bitmaps_reference/` nach

Bisher alles gut. Wir haben unseren Referenzsatz. Jetzt lassen Sie uns einen Test durchführen!
Unseren ersten Test ausführen
Wir sind dabei, unseren ersten Test auszuführen. Bedenken Sie jedoch, dass wir an unserer CSS noch nichts geändert haben, daher sollten unsere Tests bestanden werden!
Führen Sie im Verzeichnis `myCoolProject/node_modules/backstopjs/` aus
$ npm run test
Diese Aufgabe erstellt ein neues, zeitgestempeltes Verzeichnis mit Testbildern unter `/myCoolProject/backstop_data/bitmaps_test/<timestamp>`.
Sobald die Testbilder generiert sind, öffnet BackstopJS Ihren Webbrowser und zeigt einen Bericht an, der die neuesten Test-Bitmaps mit den aktuellen Referenzbildern vergleicht. Wesentliche Unterschiede (falls vorhanden) werden erkannt und angezeigt.

In diesem Fall, da wir keine Änderungen an unserer Testseite vorgenommen haben, sollte BackstopJS alle unsere Tests als bestanden anzeigen. Versuchen wir nun, unser CSS zu ändern und zu sehen, was passiert.
Aktualisieren unserer Index-Datei und Ausführen unseres zweiten Tests
Hier sehen Sie, was passiert, wenn Sie unsere (unveränderte) `myCoolProject/index.html` in einem Webbrowser öffnen. Achten Sie auf den Rand um den Text

Lassen Sie uns das vermasseln! Öffnen Sie `myCoolProject/index.html` und fügen Sie den folgenden Code direkt vor dem schließenden `</head>`-Tag ein
<style>
.jumbotron {
padding: 0px;
}
</style>
So sieht die Seite jetzt aus

Das ist genau die Art von Dingen, die bei der Webentwicklung ständig passieren. Einige nicht abgekapselte Codes geraten hinein und vermasseln Ihr Layout gerade so sehr, dass Sie es vielleicht nicht bemerken :(
Führen Sie nun im Verzeichnis `myCoolProject/node_modules/backstopjs/` aus
$ npm run test
Unser Test sollte erneut ausgeführt werden und Fehler sollten gefunden werden. Scrollen Sie den Bericht nach unten, um eine visuelle Differenz der von uns gerade erstellten Probleme zu sehen...

Unsere visuelle Differenz enthält die Referenzaufnahme, die neueste Testaufnahme und die visuelle Differenzdatei.

Da haben Sie es: Regression gefunden!
Das ist ein sehr einfaches Beispiel. Im wirklichen Leben können Designer und Ingenieure an sehr großen oder komplexen CSS-Projekten arbeiten. Dann verbessert ein System wie dieses wirklich die Qualität und Konsistenz unserer Arbeit. Durch die Automatisierung repetitiver visueller Aufgaben können wir uns zuversichtlich kreativeren zuwenden.
Über den Workflow
Es gibt viele Möglichkeiten, diese Art von Tests in Ihren Workflow zu integrieren. Sie könnten Tests jedes Mal auslösen, wenn Sie bauen, oder Sie könnten Tests manuell ausführen (während Sie arbeiten oder kurz vor dem Push in die nächste Stufe). Sie könnten BackstopJS sogar in Ihre CI-Pipeline integrieren, wenn das Ihr Ding ist. All diese Themen liegen außerhalb des Umfangs dieses Artikels. Lesen Sie die Dokumentation für weitere Informationen.
Nächste Schritte
Seit der ersten Veröffentlichung im Jahr 2014 hat sich BackstopJS erheblich weiterentwickelt. Es wurden zahlreiche neue Funktionen von der Community entwickelt
- Unterstützung für SPA-Tests – Verwenden Sie Casper-Skripte und explizite Web-App-Trigger, um sicherzustellen, dass Screenshots zur richtigen Zeit innerhalb Ihrer Web-App aufgenommen werden (z. B. nach API-Antworten, nach Abschluss von CSS-Animationen oder warten Sie auf andere beobachtbare asynchrone Prozesse).
- Simulation von Benutzerinteraktionen – Verwenden Sie Casper-Skripte innerhalb Ihrer Szenarien, um Interaktionen mit Ihren On-Screen-Komponenten zu simulieren.
- Integration in die CI-Pipeline – Die CLI-Funktionen von BackstopJS haben fortgeschrittenen Benutzern die Möglichkeit gegeben, visuelle Regressionstests zu einem Teil ihres Continuous-Integration-Prozesses zu machen.
- Aktive Konfigurationsdateien – Ermöglicht aktive (node module) Logik innerhalb Ihrer Konfigurationsdateien, die Sie verwenden können, um das Testverhalten basierend auf der Umgebung oder anderen Bedingungen zu ändern, auf unterschiedliche Konfigurationsdateien verweisen, um Ihre BackstopJS-Instanz als zentralen Testserver für mehrere Umgebungen, Verticals, Profile, Projekte oder was auch immer zu nutzen.
Mehr über BackstopJS
- BackstopJS.org
- Finden Sie Dokumentation, melden Sie Fehler, erhalten Sie Hilfe zur Fehlerbehebung, lernen Sie fortgeschrittene Funktionen kennen und tragen Sie bei auf GitHub!
Ich bin immer wieder erstaunt, wie viel es über Webentwicklung zu lernen gibt. Trotzdem fühlt es sich immer noch sehr aufregend an.
Erstaunliche Sache, kann es kaum erwarten, das auszuprobieren. Ich mag wirklich, wohin sich das Web entwickelt.
Ausprobiert und es hat mir gefallen.
Kann es kaum erwarten, dass mehr Browser-Engines unterstützt werden.
Ich bin auf ein Problem bei der Installation gestoßen.
–> sudo npm install phantomjs
Ich musste es global installieren „-g“
–> sudo npm install -g phantomjs
@Kenneth wirf einen Blick auf Gemini (https://github.com/bem/gemini) für breitere Unterstützung
Danke Bro, dass du mir geholfen hast
Coole Story, Bro. Zu schlecht wegen diesem document.ready()-Teil, das ist hier ein Dealbreaker. Ich freue mich auf das Update nächstes Jahr!
Ich auch. Ich war wirklich aufgeregt, bis ich den letzten Absatz gelesen habe. Cooles Werkzeug aber. Ich freue mich auf zukünftige Verbesserungen.
Ja, ich weiß – es ist tatsächlich ein riesiger Dealbreaker für mich bei den meisten meiner Projekte, und ich habe das Tool gebaut! Ich plane, dies als allererstes Update hinzuzufügen. Etwas wie ein Listener an der Konsole und/oder dem Fenster, der konfiguriert werden könnte mit...
BackstopJS würde warten, um einen Test auszuführen, wenn consoleOrWindowReadyEvent wahr ist. Ihre App würde also entscheiden, wann ihre Ansicht ausreichend geladen ist, und (z. B. 'everythingIsReady') auf dem Konsolen- oder Fensterknoten ausgeben – dann würden die Snapshots ausgeführt.
Jegliche Kommentare oder Vorschläge hier wären großartig. Und natürlich wären jegliche Beiträge hier herausragend. ;)
Was denkst du über Gemini?
Das beste Werkzeug für CSS-Regression im Moment :)
http://sourcejs.com/ plant ebenfalls, Unterstützung für Gemini hinzuzufügen.
Was denkst du über https://github.com/winsonwq/viff
Ich bin verwirrt, warum so viele Regressionstest-Frameworks verlangen, dass ein Benutzer Module wie Phantom und Casper global auf seinem Rechner installiert. Ich finde, das ist viel verlangt, besonders wenn man eine solche Lösung in einer CI-Umgebung integrieren möchte. Ich habe die folgenden Plugins entwickelt, lose basierend auf PhantomCSS mit der Option, ResembleJS für den Bildvergleich zu verwenden. Die CLI verwendet Phantom- und Casper-Executables anstelle einer globalen Installation
https://www.npmjs.org/package/resemble-cli
https://www.npmjs.org/package/grunt-resemble-cli
Ihr Framework ist weitaus besser als diese (da sie keine Komponenten, sondern nur vollständige Seiten aufnehmen), aber dies ermöglicht auch die Option für den Bildvergleich mit GraphicsMagick (das global installiert sein muss). Wenn es ein Modul gibt, das ich von Benutzern verlangen würde, es global zu installieren, dann wäre es GM, da ich festgestellt habe, dass der Bildvergleich in Resemble extrem langsam und in GM fast sofort ist.
Warum auch nicht dies auf NPM veröffentlichen und den Benutzern den Schritt ersparen, in ein Bower-Repo zu wechseln und npm zu installieren?
Endlich! Ich habe von so etwas geträumt, war aber zu faul, eigene Recherchen anzustellen. Jetzt, da es fast auf dem Silbertablett serviert wurde, werde ich es definitiv nutzen. TY!
Visuelle Regressionstests sind auf großen Websites, und besonders in großen Teams, sehr, sehr, sehr nützlich. Ich habe meine Erfahrungen damit bei der Implementierung unter http://sonniesedge.co.uk/2014-10-17/visual-regression-testing.html aufgeschrieben.
Charlie, mir gefällt auch die Detailtiefe des Prozesses und die Gedanken in deinem Artikel! Ich wäre auch daran interessiert, wie dies mit dem Erfassen von Komponenten für eine Styleguide kombiniert werden könnte, sowie mit einem Workflow, der uncss verwendet. Ich bin neu bei Grunt/Gulp, also hoffe ich, dass ich nicht zu tief einsteige. Chris, du bist wie immer der Beste!
Visuelle Regressionstests, falls zum Testen in einem Blog wie WordPress, wie geht das? Gibt es hier ein Tutorial, das visuelle Tests auf WordPress bespricht?
Vielen Dank
Das Problem, das ich bei bildbasierten Tests festgestellt habe, ist, dass sie nicht gut mit dynamischen Inhalten funktionieren. Bei einem kürzlich durchgeführten Projekt, das aus mehreren Single-Page-Apps besteht, haben wir das Galen Framework für einen hybriden Ansatz verwendet: Bildvergleich für statische Komponenten und UI-Messungen, Inhaltsprüfung und CSS-Regelprüfungen über Selenium. Galen handhabt beides. Es erfordert zwar eine gewisse Konfiguration, funktioniert aber auch mit Browserstack/SauceLabs, um die Handhabung von VMs zu vermeiden und Tests auf echten Geräten bereitzustellen.
In Bezug auf die vollständige Testabdeckung habe ich nichts Vergleichbares gefunden.
Ich bin bei weitem kein Meister wie Sie. Aber für „unerwartete visuelle Probleme“ habe ich in der Vergangenheit einige Tests zu Änderungen durchgeführt und in verschiedenen Browsern etc. ausprobiert – nur um kurz danach, nachdem die Änderungen auf einer Website angewendet wurden, E-Mails von Benutzern zu erhalten, die mir sagen, dass sie dieses und jenes Problem mit dem Aussehen der Website hatten, und das in GENAU demselben Browser, den ich bereits „zufriedenstellend“ getestet hatte. Die Bitmaps-Referenz ist jedoch natürlich immer noch eine brillante Idee, um Dinge aufzufangen, die ich vielleicht gar nicht erst „gesehen“ habe!
+1
Die zu testende Seite hat normalerweise dynamische Inhalte. Das bedeutet, dass sich der Inhalt ändern kann und Regressionstests fehlschlagen. Ich löse dies, indem ich auf der Entwicklungsumgebung einen Styleguide-Bereich pflege. Dies sind statische HTML-Seiten mit jeder einzelnen gestylten Komponente darauf. Abgesehen von der Testbarkeit ist es auch ein guter Beweis dafür, dass das CSS im Allgemeinen ordentlich gestaltet ist. Als eine Art Galerie ist der Styleguide sehr praktisch, wenn man eine Komponente zur Wiederverwendung auswählt. Darüber hinaus ist es technisch gesehen fast wie Unit-Testing. Regressiv oder nicht, auf diese Weise testen wir tatsächlich jede Komponentenstil unabhängig und werden auf ein Problem aufmerksam, unabhängig vom Kontext.
Hier ist die Walkthrough
http://dsheiko.com/weblog/automated-css-regressive-testing-in-practice/
Gibt es eine Version dieses Tools, die NPM und Node nicht benötigt?
Ich habe derzeit kein Interesse daran, Node auszuprobieren, und auch keine Pläne für die Zukunft, aber es scheint, dass viele nette Tools damit gebaut werden.
Gemini ist wahrscheinlich das herausragende Produkt im Moment. Es nutzt Selenium und PhantomJS und ermöglicht Cross-Browser-Regressionstests.
https://github.com/gemini-testing/gemini
Das ist ja großartig!
Toller Beitrag und danke fürs Teilen, Garris Shipon.
Prost!
Ich habe versucht, dies zu verwenden, aber beim Ausführen von
„npm run reference“
erhalte ich folgende Fehlermeldung
”’
BackstopJS Config geladen an Position D:\www\demo\backstop.json
[09:34:41] Gulpfile D:\www\demo\node_modules\backstopjs\gulpfile.js wird verwendet
[09:34:41] Starte „echo“...
CasperJS wird ausgeführt mit: [ ‘capture/echoFiles.js’ ]
[09:34:41] „echo“ nach 16 ms abgeschlossen
Echo-Dateien fehlgeschlagen mit Code: 1
”’
Ich führe dies unter Windows 10 mit installiertem NPM und NodeJS aus
Ich habe denselben Fehler wie Sie. Haben Sie eine Lösung dafür gefunden?
Bitte posten Sie alle Probleme auf GitHub. Danke! https://github.com/garris/BackstopJS/issues
Gut gemacht, Garris!