Visuelle Regressionstests
Mit dem folgenden npm Befehl installiert man Backstop global (natürlich ist auch eine lokale Installation oder die Einbindung zum Beispiel in einen Gulp-Task möglich). Voraussetzung ist natürlich das node.js installiert ist und falls ihr nvm nutzt, achtet darauf das ihr mindesten node Version 12 verwendet, ansonsten kann es Probleme mit dem Download des Chromium-Treiber geben.
npm install -g backstopjs
In ein Verzeichnis wechseln, bzw. eines erstellen, z.B. testing/backstop:
backstop init
Der init Befehlt installiert einige Beispiel-Dateien. Man kann die URL in der backstop.json durch eine eigene ersetzen und einen ersten Test ausführen. Zeile 21:
"url": "https://garris.github.io/BackstopJS/",
Natürlich kann man auch für komplexere Umgebungen zum Beispiel ein env-File mit Variablen erstellen.
Zuerst erstellt man Reference-Dateien (Referenz kann eine Website auf Localhost sein oder die ein produktive Website (dafür ist der key referenceUrl vorgesehen, bei Tests ausschließlich gegen eine lokalen Installation kann der Wert leer bleiben).
Reference Bilder erstellen
backstop reference
Nun kann gegen die Referenz ein erster Test durchgeführt werden.
backstop test
Fertig. Jetzt kann bei jeder Änderung im Code überprüft werden: Hey Frontend, bist du stabil.
Voll.
Login in eine Drupal Website
Hier meine Beispiel backstop.json - wer genau hinschaut, sieht, dass ich ich gegen ein Drupal Backend teste, dafür habe ich mir ein kleines Puppeteer Script gebaut. Keys ohne Value können übrigens gelöscht werden.
Hier eine backstop.json mit drei Beispiel-Scenarios:
{
"id": "backstop_default",
"viewports": [
{
"label": "phone",
"width": 320,
"height": 480
},
{
"label": "tablet",
"width": 1024,
"height": 768
}
],
"onBeforeScript": "puppet/onBefore.js",
"onReadyScript": "puppet/onReady.js",
"scenarios": [
{
"label": "Homepage",
"cookiePath": "backstop_data/engine_scripts/cookies.json",
"url": "http://gnuschichten.test/",
"referenceUrl": "",
"readyEvent": "",
"readySelector": "",
"delay": 0,
"hideSelectors": [],
"removeSelectors": [],
"hoverSelector": "",
"clickSelector": "",
"postInteractionWait": 0,
"selectors": [],
"selectorExpansion": true,
"expect": 0,
"misMatchThreshold" : 0.1,
"requireSameDimensions": true
},
{
"label": "Header",
"url": "http://gnuschichten.test/",
"postInteractionWait": 0,
"selectors": [
".section .section--header"
]
},
{
"label": "DrupalBackend",
"onBeforeScript": "puppet/userLogin.js",
"url": "http://gnuschichten.test/",
"delay": 1000,
"hideSelectors": [
".messages-list"
],
"selectors": [
".page-wrapper"
]
}
],
"paths": {
"bitmaps_reference": "backstop_data/bitmaps_reference",
"bitmaps_test": "backstop_data/bitmaps_test",
"engine_scripts": "backstop_data/engine_scripts",
"html_report": "backstop_data/html_report",
"ci_report": "backstop_data/ci_report"
},
"report": ["browser"],
"engine": "puppeteer",
"engineOptions": {
"args": ["--no-sandbox"]
},
"asyncCaptureLimit": 5,
"asyncCompareLimit": 50,
"debug": false,
"debugWindow": false
}
Die Debug Optionen sind sehr nützlich und über DebugWindow true bekommt der Headless-Chromium wieder einen Kopf und man kann ihm beim Testen zuschauen.
Mein Login-Script unter backstop_data/engine_scripts/puppet/userLogin.js
module.exports = async (page, scenario) => {
await page.goto('http://gnuschichten.local/user/login');
await page.click('input#edit-name');
await page.type('input#edit-name', 'admin');
await page.type('input#edit-pass', 'admin');
await page.click('button#edit-submit');
await page.waitFor(10000);
await page.goto(scenario.url);
};
Der Wert für die Url muss angepasst werden.
Natürlich kann man auch Cookies über den entsprechenden Key verwenden, die Beispiel-Installation über backstop init liefert die entsprechenden Hinweise. Ein Cookie-Hinweis kann aber auch unkompliziert über den Schlüsselwert "removeSelectors" entfernt werden. Überhaupt würde ich empfehlen keine ganzen Seiten zu testen, sondern nur Komponenten (siehe Scenario "Header").
Hier noch ein paar interessante Links:
Einige interessante Puppeteer Scripts und eine Gulp Integration findet hier (Backstop-Testing für eine Drupal-based CiviCRM).
Wichtig, wenn ihr Tests auf verschiedenen Rechner durchführt, kann es z.B. aufgrund leicht abweichender Schriftarten auf unterschiedlichen Betriebssystem zu fehlschlagenden Test kommen. Deshalb ist es besser Backstop in einen Docker-Contaioner auszulagern. Der Maintainer von BackstopJS selbst erklärt in dieser Issue, wie das geht:
github.com/garris/BackstopJS/issues/796