Style Tests mit Selenium und Robotframework

Keine Kommentare

In Projekten mit Endkundensichtbarkeit kommt es oft auf das genau Aussehen der Anwendung an. In internen Anwendungen ist es häufig egal ob und wie viel sich das Aussehen der Oberfläche verändert, jedoch mag es auch dort Kunden geben welche sehr strikte Richtlinien für den Style der Anwendung haben damit es sich nahtlos in ihre Corporate Identity einfügt.
Wer jemals mit HTML und pixelgenauem CSS gearbeitet hat, weiß wie leicht Fehler passieren können oder wie schnell man bereits bestehendes Design beeinflusst. Selbst ein durchdachtes Layout oder strenge Designrichtlinien können dies nicht immer verhindern.
Letzten Freitag haben wir in unserem Team diskutiert was wir tun können damit uns das nicht passiert. Schnell war klar, daß wir auch diese Anforderung im nightly build abbilden wollen.
Es war überraschend einfach…

Die Idee

Wenn ein Entwickler das HTML und CSS für eine Komponente, wie Login oder Einkaufswagen, entwickelt hat und sichergestellt hat, daß es auch in allen geforderten Browsern richtig ausschaut, erstellt er einen Screenshot. Dann schneidet er, wie z.b. rechts zu sehen, den erstellten Bereich aus. Dieser Teil agiert dann als Referenz.
Als nächstes muss dem automatischem Build noch mitgeteilt werden auf welcher Seite dieser Bereich erwartet wird. Dies kann zum Beispiel eine Seite mit einem Benutzer sein, welcher einen bestimmten Artikel im Warenkorb hat. Der Test macht dann dort einen Screenshot und sucht in diesem nach dem erwarteten Bereich.
Wir haben auch in Erwägung gezogen noch genauer festzulegen an welchen Koordinaten dieser Bereich auftauchen muss, jedoch macht dies mehr Arbeit als es abnimmt. So ist bei vielen Layouts die Position relativ zur Fenstergröße. Auch ist die Pflege dieser Koordinaten mühselig.
Wenn man über das Problem nachdenkt kommt man zu dem Entschluss, daß die alleinige Existenz völlig ausreichend ist. Selbst wenn man Abstände und relative Positionierung Prüfen will, so macht man einfach einen Screenshot des entsprechenden Abstandes.

Die Umsetzung

Also schrieben wir ein einfaches Robot keyword, welches einen Screenshot auf einer bestimmten URL macht. Dies lässt sich leicht mit anderen Aktionen, wie einloggen oder Warenkorb befüllen kombinieren. Anschließend prüft das Keyword den Screenshot. Es ist natürlichsprachlich geschrieben und sieht in etwa so aus:

*** Keywords ***	
 
Match Styles ${Styles}
    Execute Javascript  window.resizeTo(100,100)
    ${ID} =  Get Unique ID
    Capture Page Screenshot  ${OUTPUT DIR}${/}StyleTest-${ID}.png  css=
	:FOR  ${style}  IN  @{Styles}
    \	Match Style  ${CURDIR}${/}styles${/}${style}.png  ${OUTPUT DIR}${/}StyleTest-${ID}.png
    Remove File  ${OUTPUT DIR}${/}StyleTest-${ID}.png

Das Javascript dient dazu die Größe des Screenshots zu reduzieren, indem es variablen Whitespace komprimiert. Dadurch ist ausserdem die Suchfunktion schneller. Get Unique ID generiert eine ID mittels Java UUID.

Das Java Keyword ist einfach:

public static void matchStyle(String expectedFilename, String actualFilename) throws IOException {
	boolean check = StyleChecker.check(expectedFilename, actualFilename);
	if (!check) {
		throw new IllegalStateException("could not find expected image in actual screenshot");
	}
}

Die eigentliche Suche ist auch in Java implementiert. Der Code ist nicht besonders raffiniert, aber nach einigen Optimierungen doch ziemlich schnell (Im schlimmsten Fall etwa 300ms falls das erwartete Bild nicht gefunden wird. Im normalfall etwa um die 200ms). Das Erstellen des Screenshots ist hingegen schon deutlich langsamer.
Der Java Code kann heruntergeladen werden und ist hier aus Platzgründen ausgelassen.

Ein Test kann dann so aussehen:

*** Keyword ***
Verhalten
    [Arguments]  ${Url}  @{Styles}
 
    Go To  ${Url}
    Match Styles @{Styles}
 
| *Test Case* | | *Url*                        | *style*          |
| 1 | Verhalten | http://${BASE_URL}${CONTEXT} | Login | Warenkorb-Leer|

Fallstricke

  1. Die Screenshots und Vorlagen müssen verlustfrei sein.
  2. Mein Code ist pixelgenau. Das bedeutet, daß jedes klitzekleine Detail wichtig ist. Deshalb ist es besser den von Selenium erstellten Screenshot zu verwenden, da dieser sich wahrscheinlich von einem Entwicklerscreenshot unterscheidet. Insbesondere ClearType oder Fonts können den Unterschied machen.
  3. Bildvergleich in Java ist nicht trivial. Ich hoffe daß mein Code nicht ganz so schlimm ist, da ich ihn ausreichend getestet und profiled habe. Für Verbesserungen bin ich jederzeit zu haben.

Vorteile

Durch diese einfachen Schritte sind wir nun in der Lage Regressionstest für den Style der Webanwendung zu machen, da einige Teile sehr strengen Anforderungen genügen müssen. Auch ist das Setup besonders einfach. Innerhalb von Sekunden können sich beliebig viele weitere Tests erstellen.

Fehleranalyse

Was passiert, wenn ein Styletest fehlschlägt? Oft ist die Analyse recht einfach, denn die Stylefehler die mit dieser Art von Tests gefunden werden sollen (Abstände falsch, Farben passen nicht, falsches Bild, etc.) lassen sich dann auch mit einem Blick auf den Screenshot erkennen. Jetzt gerade hatten wir aber den Fall, dass wir mit bloßem Auge die Unterschiede nicht erkennen konnten, und schon ein misslungenes Refactoring in Verdacht gezogen haben. Zu Unrecht! Um Unterschiede zwischen zwei Bildern herausfinden zu können, bietet sich GIMPs Ebenenmodus „Unterschied“ an, eventuell muss man den dann entstehenden schwarzen Bereich noch aufhellen, um die tatsächlichen Unterschiede zu sehen:

  • Screenshot (1) in GIMP laden
  • Bild, das im Screenshot gefunden werden soll, (2) in GIMP laden
  • Bild (2) als neue, halbtransparente Ebene über den Screenshot (1) legen
  • Der neuen Ebene den Modus „Unterschied“ geben
  • Sichtbare Ebenen zusammenfügen
  • Dunkle Bildanteile aufhellen (Ebenen -> Werte), um die Unterschiede hervorzuheben

Soweit die Kurzanleitung, falls dabei Probleme auftauchen, bitte in den Kommentaren melden.

Fabian Lange ist Lead Agent Engineer bei Instana und bei der codecentric als Performance Geek bekannt. Er baut leidenschaftlich gerne schnelle Software und hilft anderen dabei, das Gleiche zu tun.
Er kennt die Java Virtual Machine bis in die letzte Ecke und beherrscht verschiedenste Tools, die JVM, den JIT oder den GC zu verstehen.
Er ist beliebter Vortragender auf zahlreichen Konferenzen und wurde unter anderem mit dem JavaOne Rockstar Award ausgezeichnet.

Share on FacebookGoogle+Share on LinkedInTweet about this on TwitterShare on RedditDigg thisShare on StumbleUpon

Kommentieren

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.