Difference Testing mit recheck-web: Von der Installation bis zur Stabilisierung

Der erste recheck-web-Testfall

Ein einfacher Test mit Selenium und recheck-web könnte in Java ungefähr so aussehen:

?package com.mycompany;

import org.junit.*;
import org.openqa.selenium.*;
import de.retest.recheck.*;

public class MyFirstTest {

private WebDriver driver;
private Recheck re;

@Before
public void setup() {
? re = new RecheckImpl();
? System.setProperty("webdriver.chrome.driver", "C:\\pathto\\chromedriver.exe");
driver = new ChromeDriver();
}

@Test
public void google() throws Exception {
re.startTest();

driver.get("http://google.com");
re.check(driver, "open");

re.capTest();
}

@After
public void tearDown() {
driver.quit();
re.cap();
}
}

Die mit @Before annotierte Methode erstellt sowohl die zu verwendende Recheck-Instanz als auch den ChromeDriver. Die mit @Test annotierte Methode teilt zuerst recheck mit, dass der Test startet (durch Aufruf von startTest), und lädt dann die Google-Startseite in Chrome. Danach wird die aktuelle Version der Seite überprüft, indem sie mit dem Aufruf von check mit dem Golden Master (wird später erklärt) verglichen wird. Dabei vergibt das Werkzeug eine semantische und eindeutige Kennung.

In einem typischen umfangreicheren Test rufen Entwickler check mehrmals auf, jedes Mal mit einer anderen eindeutigen Kennung. Da Unterschiede nicht so ungewöhnlich sind, ist es nicht gewünscht, dass der Test bei einem kleinen Unterschied sofort fehlschlägt. Deshalb werden bei den Aufrufen der Prüfmethode alle Abweichungen gesammelt. Um den Test im Fall von Differenzen fehlschlagen zu lassen, rufen Entwickler am Ende des Tests die Methode capTest auf. Sollten sie den Aufruf vergessen, findet sich eine entsprechende Meldung in der Logausgabe. Nach Abschluss des Tests beendet die @After-Methode Chrome durch den Aufruf von driver.quit() und veranlasst via cap das Erstellen einer zusammenfassenden Berichtsdatei inklusive aller Änderungen.

Lokale Ausführung eines ersten Testfalls

Nun sollten Entwickler den Test mit mvn test ausführen können. Wenn alles korrekt eingerichtet wurde, sieht man beim ersten Ausführen des Tests die folgende Fehlermeldung:

?java.lang.AssertionError: 'com.mycompany.MyFirstTest':
No recheck file found. First time test was run? Created recheck file now, don't forget to commit...
at de.retest.recheck.RecheckImpl.capTest(RecheckImpl.java:137)
? at com.mycompany.MyFirstTest.google(MyFirstTest.java:30)
at ... some more stack trace ...

Die erneute Überprüfung erfolgt, indem der aktuelle Zustand der Software (d. h. in diesem Fall der Website) mit einer Referenz namens Golden Master aus einem früheren Zustand der Software verglichen wird. Lässt sich kein solcher Master finden, wirft recheck einen Fehler. Das ist das erwartete und gewünschte Verhalten. Denn sollten Entwickler vergessen, ihren Golden Master in ihrem Versionskontrollsystem zu committen, oder ein Pfad ändert sich und der Golden Master ist nicht auffindbar, dann ist ein Fehlschlagen des Tests erwünscht.

Der Test muss also beim ersten Ausführen fehlschlagen. Aber recheck erzeugt genau dann den Golden Master und legt ihn unter src\test\resources\retest\recheck\com.mycompany.MyFirstTest\google.open.recheck ab. Im Ordner befindet sich nun eine XML-Datei, die alle Attribute jedes HTML-DOM-Elements nach dem Rendern der Website enthält, sofern es sich nicht um die Standardwerte handelt, zusammen mit einem Screenshot der Website. Wenn Entwickler nun ihren Test erneut ausführen, werden alle Elemente und Attribute des Golden Master mit den aktuellen HTML-DOM-Elementen verglichen. Jede nicht ignorierte Differenz eines Elements führt zum Fehlschlagen des Tests. Führen Entwickler das erneut aus (wiederum mit mvn test), wird eine Ausgabe (ohne ignorierte Elemente) ähnlich der folgenden erzeugt:

?java.lang.AssertionError:
A detailed report will be created at 'target\test-classes\retest\recheck\com.mycompany.MyFirstTest.report'. You can review the details by using our GUI from https://retest.de/review/.

The following differences have been found in 'com.mycompany.MyFirstTest'(with 1 check(s)):
Test 'google' has 37 differences in 1 states:
open resulted in:
A [About Google] at 'HTML[1]/BODY[1]/DIV[1]/DIV[3]/DIV[1]/DIV[1]/A[1]':
? ping: expected="some gibberish"
? ... many more differences ...

Die erneute Prüfung zeigt wirklich alle Unterschiede aller Attribute an. Das ist vergleichbar mit der Verwendung von Git ohne Konfiguration in einem bestehenden Projekt: Es zeigt alle Unterschiede, einschließlich Protokolldateien, Binärdateien und vielen anderen Dateien, die normalerweise nicht von Interesse sind. Glücklicherweise erlaubt es Git, diese Unterschiede via .gitignore einfach zu ignorieren.

recheck funktioniert ähnlich: Entwickler können alle volatilen und nicht relevanten Unterschiede einfach ignorieren. Das Werkzeug hat einen Ordner mit dem Namen .retest im Projektverzeichnis erstellt. Dort findet man ein Beispiel für die Datei recheck.ignore. Um diese flüchtigen Elemente zu ignorieren und den gegebenen Test grün werden zu lassen, müssen Anwender nur diese Klartextdatei bearbeiten. Das Einfügen des folgenden Inhalts in die Datei sollte den Test erfolgreich durchlaufen lassen:

?attribute=ping
attribute=jsdata
attribute=data-.*
attribute=class
attribute=outline
attribute=transform

Da Google seine Website ständig ändert, müssen Entwickler möglicherweise einige weitere Attribute hinzufügen. Aber das ist nicht schwierig, und selbst das Ignorieren von Attributen durch Platzhalter (mit dem Mechanismus des Java-Pattern) ist möglich. Die erzeugte Datei recheck.ignore enthält Beispiele, wie man ganze Teilbäume des DOM oder bestimmte Attribute bestimmter Elemente vernachlässigen kann. Weitere Informationen finden sich in der Dokumentation. Der Mechanismus erlaubt es zum Beispiel, die Schriftart eines Texts zu ignorieren, aber nicht den Text selbst. Der semantische Ignore-Mechanismus ist eines der Kernmerkmale von recheck.

Je nachdem, was Entwickler in der Ignore-Datei angeben, lassen sich verschiedene Testszenarien realisieren. Der allgemeine Mechanismus von recheck ermöglicht es, Funktionstests, Cross-Browser- und Cross-Device-Tests sowie visuelle Regressionstests zu erstellen und durchzuführen. Für die letzteren Testzwecke sollten Entwickler vorsichtig sein mit dem, was sie ignorieren. Für reine Funktionstests können sie meist problem- und risikolos viele CSS-Attribute vernachlässigen.