Test von Webanwendungen – auf das Werkzeug kommt es an
Für Tests von Webanwendungen auf der obersten Ebene der Testpyramide – dem benutzerzentrierten UI-Test – gibt es eine Reihe von Werkzeugen. Bei genauer Betrachtung basieren viele der Werkzeuge auf ähnlichen Architekturen. Im Folgenden geben wir einen Überblick über verschiedene Ansätze zur Steuerung und Kontrolle von Webanwendungen, um Ihnen bei der Auswahl des richtigen Werkzeugs zu helfen.
In den letzten Jahren hat sich der Webbrowser zur dominierenden Plattform für User-Interfaces entwickelt. Browser sind inzwischen auf fast allen Geräten verfügbar und wurden schrittweise als allgemeine UI-Plattform ausgebaut. Anders als die "am Reißbrett" entwickelten APIs von Betriebssystemen war die Entwicklung der Browser von der Darstellung wissenschaftlicher Artikel hin zur interaktiven UI-Plattform eher dynamisch bis chaotisch. Heute sehen sich Entwickler:innen von Webanwendungen einem mehr oder weniger gut integrierten Sammelsurium von Techniken, Sprachen und Frameworks gegenüber. Die Entwicklungszyklen werden immer kürzer, die technische Basis ändert sich immer schneller. Anwendungsarchitekturen reichen von Multi-Page-Applikationen mit mehr oder weniger dynamischen Anteilen bis hin zu modernen Single-Page-Applikationen, bei denen der gesamte Inhalt einer einzigen Seite dynamisch ausgetauscht wird, um sich der Mächtigkeit von Rich-Client-Anwendungen zu nähern. Trotz voranschreitender Standardisierung gibt es immer noch erhebliche Unterschiede zwischen den Browsern, was den Testaufwand deutlich erhöht, da Funktionalitäten in verschiedenen Konstellationen von Browser(-Versionen) und Betriebssystemen getestet werden müssen.
Dieser rasante technische Wandel hat natürlich auch Auswirkungen auf den Test. Die schnellen Entwicklungszyklen sind ohne Testautomatisierung nicht mehr zu beherrschen. Gerade der aufwändige Test des UIs verlangt nach guten Werkzeugen, die sowohl eine effiziente Erstellung und Pflege der Tests als auch eine stabile Ausführung garantieren. Hier stellte insbesondere der hohe Anteil an asynchroner Verarbeitung in modernen Webapplikationen eine zusätzliche Herausforderung dar. Wer schon einmal mit täglich wechselnden Blinkern gekämpft hat, kennt die Versuchung, die UI-Testautomatisierung einfach zu deaktivieren – mit negativen Folgen für die Qualität des Softwareprodukts. Deshalb ist es umso wichtiger, neben der richtigen Herangehensweise auch das richtige Werkzeug auszuwählen.
Wunsch...
Beginnen wollen wir mit unserer persönlichen Wunschliste für die Testwerkzeuge. Wir werden verschiedene Tools mit jeweils verschiedenen Architekturen vorstellen und anhand dieser Kriterien kurz bewerten.
- Robustheit: Technische Änderungen sollte keinen oder nur wenig Einfluss auf den Test haben, d. h. der Test sollte bei technischen Änderungen weder angepasst werden müssen noch fehlschlagen. So sollten bspw. Änderungen an der inneren Struktur von Seiten oder einzelnen Controls (DOM-Baum) keine Änderungen am Test erfordern.
- Sensitivität: Im Gegensatz zur Robustheit bei technischen Änderungen sollten die Tests sensibel auf fachliche Änderungen reagieren. Nur so können z. B. Seiteneffekte von Änderungen oder Unterschiede bei der Verwendung verschiedener Browser sicher erkannt werden.
- Wartbarkeit: Tests sollten einfach zu schreiben und einfach zu erweitern – kurz wartbar – sein. Das Testprotokoll sollte im Fehlerfall alle Informationen enthalten, die für ein schnelles Beheben des Fehlers notwendig sind. Insbesondere die Entscheidung, ob ein Fehler in der Anwendung oder im Test vorliegt, muss einfach und schnell getroffen werden können. Da Tests Fehler nicht selten erst später im Workflow detektieren, als sie eigentlich aufgetreten sind, sollte der Testbericht eine gute Analyse aller vorangegangenen Testschritte ermöglichen.
- Lesbarkeit: Das Testprotokoll ist ein wichtiges Kommunikationsmittel. Ein verständliches Testprotokoll führt zu Vertrauen bei den Stakeholdern und ermöglicht eine enge Zusammenarbeit mit den Entwicklern. So können doppelte Tests oder Testlücken zwischen den Unittests und den UI-Tests vermieden werden.
Werfen wir nun einen Blick auf unterschiedliche Werkzeuge für den UI-Test von Webanwendungen. Können die untersuchten Werkzeuge diese Kriterien erfüllen?
…und Wirklichkeit
Wir haben vier Werkzeuge mit jeweils einem eigenen Ansatz ausgewählt, Tests im Browser auszuführen. Neben Selenium sind das Wetator, Sahi und Cypress[1].
Unsere Auswahl betrachtet ausschließlich Open-Source-Werkzeuge. Da ein großer Teil der kommerziell verfügbaren Werkzeuge auf Selenium bzw. dessen WebDriver-API basiert, ist diese Beschränkung jedoch nicht erheblich.
Die in diesem Artikel als Beispiel dienende einfache Formularanwendung wurde sowohl als Angular-App als auch als reine Javascript-Anwendung programmiert. Letzteres war notwendig, da (bisher) weder Wetator noch Sahi korrekt mit Angular umgehen können. Unterschiede in den Testskripten, die einen identischen Testfall spezifizieren, sind den Möglichkeiten der Werkzeuge geschuldet.
Selenium – der Platzhirsch
Denkt man an Web-UI-Tests, fällt wohl in den meisten Fällen als erstes der Name Selenium. Das verwundert nicht, war Selenium doch eines der ersten Automatisierungswerkzeuge für Web-Tests, das schon sehr früh unter einer Open-Source-Lizenz verfügbar war. Die Selenium-Familie umfasst inzwischen verschiedene Lösungen, so ist neben der eigentlichen Browsersteuerung bspw. auch ein Recorder zum Aufzeichnen und ein Test-Runner zum Abspielen von Tests vorhanden. Kern der (Fern-)Steuerung der Browser bildet der WebDriver, auf den wir in diesem Artikel genauer eingehen werden [2].
Selenium steuert den Browser "von außen", über die bereits erwähnte WebDriver-Schnittstelle. Das ist ein Zusatzprogramm, das von den Browserherstellern (Ausnahme IE) bereitgestellt wird. Selenium kommuniziert dann über eine HTTP-Schnittstelle mit dem WebDriver und stellt ein High-Level-API zur Interaktion bereit. Das WebDriver-API ist inzwischen ein W3C-Standard. Durch diese Architektur wird eine (fast) perfekte Simulation des Nutzerverhaltens erreicht, d. h. für die Applikation besteht kein erkennbarer Unterschied zwischen einer Bedienung durch den Anwender oder durch Selenium. Das schließt eine Darstellung der Webseite während des Tests im Browser ein. Inzwischen bieten Chrome/Edge und Firefox in der jeweiligen WebDriver-Schnittstelle die Möglichkeit, den Browser headless zu starten. Eine Darstellung der Webseiten auf dem Bildschirm wird dann unterdrückt, wobei das eigentliche Layouting aber trotzdem durchgeführt wird.
Die Kommunikation zwischen Testtreiber und Browser, und damit auch der Ablauf der Tests, folgt einem Select-Interact Pattern. Es wird stets im ersten Schritt mit einer Query ein spezifisches DOM-Element der Webseite ausgewählt und dann im zweiten Schritt eine Interaktion mit dem Element durchgeführt. Es gibt keine Möglichkeit (außer mit ineffizienten Workarounds) den gesamten DOM Baum zu erfragen. Diese Architektur ist eine große Einschränkung der WebDriver-API. Der Testdriver kann keine Analyse der Seitenstruktur vornehmen, um auf dieser Basis z. B. eine intelligente Suche nach Controls zu implementieren. Für das Selektieren eines Elements stehen in Selenium viele Methoden zur Verfügung, so kann entweder per Selenium-API, per CSS-Selektor oder per XPath gesucht werden. Allerdings sind alle diese Verfahren sehr eng mit der technischen Umsetzung der Seite verbunden. So kann z. B. schon das Einfügen eines zusätzlichen DIV-Tag in die Seite dazu führen, dass die Elementsuche fehlschlägt (oder ein anderes Element selektiert wird). Deshalb ist die Gestaltung der Element-Selektoren bei Selenium-Tests extrem schwierig und erfordert viel Erfahrung.
Um diesem Problem zu begegnen, hat sich beim Testen von Webapplikationen mit Selenium die Bereitstellung von sogenannten PageObjects für jede Oberfläche etabliert [3]. Dabei wird zusätzlich zur Webapplikation von den Entwicklern eine Reihe von PageObjects zur Verfügung gestellt, die dem Tester einen nicht technischen Zugriff auf die verschiedenen Seiten der Applikation bieten. Das jeweilige PageObject übersetzt dann den fachlichen Aufruf aus dem Testscript jeweils in einen technisch korrekten Selektor. Ändern sich die technischen Details einer Seite, so müssen die Entwickler auch die PageObjects anpassen. Die Abhängigkeit zwischen der Entwicklung und dem Test macht die Tests intransparent und Tester sind auf den Support durch die Entwickler angewiesen.
Viele weitere Open-Source-Werkzeuge setzen auf Selenium auf, adressieren in einigen Fällen die Nachteile, können aber natürlich nicht die architekturbedingten Schwächen komplett beheben. In diesem großen Feld der seleniumbasierten Tools und Erweiterungen findet sich meist für jedes System eine passende Selenium-Variante. Tests lassen sich aufnehmen und wieder abspielen oder in einer der vielen, von Selenium unterstützten, Programmiersprachen formulieren. Diese Flexibilität ist ein großer Pluspunkt, der Selenium auch heute noch zum meist eingesetzten Web-Test-Werkzeug macht.
Unser Fazit zu Selenium:
- Robustheit: Die Selektoren zum Finden der Bedienelemente sind anfällig für technische Änderungen. Die Tests müssen sich durch geeignetes Warten auf bestimmte Zustandsänderungen um die Asynchronität der Anwendungen kümmern. Da Selenium echte Browser für den Test nutzt, ist jedoch gleichzeitig eine sehr gute Aussage über die Browserkompatibilität der getesteten Anwendung möglich.
- Sensitivität: Selenium erlaubt den Zugriff auf alle Eigenschaften von Elementen und kann alle möglichen Useraktionen auslösen (incl. Drag-and-drop). Dadurch erliegen Tester gerne der Versuchung, extrem detaillierte Tests zu schreiben. PageObjects werden von den Entwicklern gerne feingranular gebaut (z. B. für einzelne Controls) und dann an vielen Stellen in den Tests wiederverwendet. Damit ist ein verlässlicher Test auf Seiteneffekte nicht mehr möglich.
- Wartbarkeit: Wie auch bei der Robustheit und Sensitivität ist hier der Tester, bei der Verwendung von PageObjects in enger Zusammenarbeit mit dem Applikationsentwickler, weitestgehend selbst verantwortlich. Nach unserer Erfahrung erfordert das vom Ersteller der Tests viel Fingerspitzengefühl, eine Portion Weitsicht und ständiges Verbessern der Testsuiten. Auch wenn Selenium das Aufzeichnen von Testscripts unterstützt, so sind diese in der Regel nicht gut wartbar.
- Lesbarkeit: Auch die Lesbarkeit der Tests und Testergebnisse hängt sehr stark von der Art der Nutzung von Selenium ab. Für einen lesbaren Report ist viel Anpassung und Eigeninitiative erforderlich, andere Werkzeuge bieten hier deutlich bessere Testreports.
Wetator – der Minimalist
Als zweites Werkzeug betrachten wir Wetator, das in vieler Hinsicht konträr zu Selenium funktioniert. Startet Selenium für die Tests echte Browser, so benutzt Wetator eine Browser-Emulation. Dazu setzt Wetator auf HtmlUnit, eine komplett in Java geschriebene Emulation, die das Verhalten von Chrome/Edge, Firefox und IE simuliert [4]. HtmlUnit arbeitet headless, es erfolgt also kein Layouting der Webseite. Deshalb kann weder das Layout noch das Styling getestet werden, auch Drag-and-drop ist nicht testbar. Neben dem Zugriff auf den kompletten DOM erlaubt HtmlUnit auch die Auswertung des Zustands der JavaScript Engine, so dass keine expliziten Waits im Tests notwendig sind.
Der große Vorteil einer Browser-Emulation ist die Betriebssystemunabhängigkeit und das schnelle Ausführen von Tests, da das zeitintensive Hochfahren des Browsers und der Layoutschritt wegfällt. Gleichzeitig hat jede Simulation Defizite, die bei HtmlUnit insbesondere im Javascript-Support, der auf der Basis von Rhino implementiert ist, liegen [5]. Neben Wetator setzen auch andere Testwerkzeuge auf HtmlUnit auf, z. B. Spring MVC Tests[6].
Wetator stellt keine Aufnahmefunktion zur Verfügung, stattdessen wird ein extrem einfaches Befehlsset angeboten. Das Ansprechen von Elementen erfolgt rein über auf der Webseite sichtbare Texte, somit wird keinerlei Kenntnis über den technischen Aufbau der Webseite benötigt. Wetator schafft es, mit Hilfe von Heuristiken die Bedienelemente auf "intelligente" Art zu identifizieren. So entscheidet in der Regel der interne Algorithmus, ob der Text des Labels vor einem Eingabeelement, der Name oder die ID zur Identifikation gemeint ist, indem mit Prioritäten gearbeitet wird, was erstaunlich gut funktioniert. Sollte Wetator einmal falsch entscheiden, ist aber auch eine genauere Angabe möglich. Da bei jedem Schritt ein Screenshot inklusive einer Markierung des selektierten Elements gespeichert wird, hat man als Tester jederzeit die volle Transparenz.
Asserts erfolgen über eine normalisierte Form der Webseite, die viele Layoutinformationen ignoriert. Damit sind nur eingeschränkte Möglichkeiten für die Überprüfungen gegeben. Da auch andere Formate, wie bspw. PDF-Dateien, in diese normalisierte Form übertragen werden können, kann der Test den Inhalt von heruntergeladenen oder angezeigten Dateien ebenfalls berücksichtigen. Neben expliziten Asserts werden auch implizite Asserts verwendet, bspw. enthält der Klick auf einen Button stets auch die Überprüfung der Existenz und der Sichtbarkeit.
Der Testbericht enthält für jeden Testschritt Vorher-/Nachher-Screenshots der Webseite, wobei das zur jeweiligen Aktion gehörende Element markiert wird. So lassen sich Fehler im Test gut analysieren und der gesamte Ablauf des Tests einfacher nachvollziehen.
Auch wenn Wetator aufgrund seiner einfachen Bedienbarkeit ein idealer Kandidat für den UI-Test zu sein scheint, lassen sich die Defizite der Browser-Simulation nicht wegdiskutieren. HtmlUnit versucht zwar, mit der Browserentwicklung Schritt zu halten, kann deren Verhalten jedoch nicht in allen Details korrekt nachbilden. Trotzdem sind Tests mit Wetator eine gute Näherung an das echte Verhalten der Anwendung im Browser und besonders für fachliche Tests geeignet.
Listing: Wetator-Script
open-url || localhost assert-content || Form Application # set || Input || Test Input set || Substring || Test click-on || Count Substrings assert-content || Test is contained 1 time(s) in Test Input # set || Input || Test Input Test click-on || Count Substrings assert-content || Test is contained 2 time(s) in Test Input
Unser Fazit zu Wetator:
- Robustheit: Durch die intelligente Suche und die enge Integration mit der Javascript-Verarbeitung sind Wetator-Tests sehr robust gegenüber technischen Änderungen. Der Zugriff auf den kompletten DOM erlaubt es, die Tests weitestgehend unabhängig von der technischen Umsetzung zu definieren.
- Sensitivität: Wetator konzentriert sich auf die Fachlichkeit der Webanwendung und nicht auf die technischen Details. Da eine normalisierte Form der Seite dem Test zugrunde liegt, wird von Merkmalen wie Layout abstrahiert, was den Test fokussierter macht. Diese Layout/Style- Merkmale und auch Drag-and-drop sind jedoch nicht testbar, selbst wenn sie für die fachliche Umsetzung relevant wären.
- Wartbarkeit: Wetator-Tests sind einfache Skripte, die Wartung ist deshalb sehr einfach. Das Skript selbst ist leicht lesbar, die Auswahl der Elemente erfolgt aus Benutzersicht. Zur Wartbarkeit trägt zudem der detaillierte Testbericht mit den Screenshots inklusive der identifizierten Elemente bei.
- Lesbarkeit: Der Standard-Report ist einfach zu lesen und alle Testschritte sind anhand der Screenshots für alle Projektbeteiligten nachvollziehbar. Eigene Reports sind per XSLT realisierbar.
Sahi – der Außenseiter
Als drittes Werkzeug werfen wir einen Blick auf Sahi. Sahi, ursprünglich als Open-Source-Projekt gestartet, ist inzwischen kommerziell, aber eine jeweils etwas ältere, eingeschränkte Version ist immer noch als Open-Source verfügbar.
Die Architektur unterscheidet sich grundlegend von den bisher vorgestellten Werkzeugen. Um die Webanwendung steuern zu können, schiebt sich Sahi als Proxy zwischen die Applikation und den Webserver und injiziert eigenen Javascript-Code in die Webseite. Dieses Script nimmt dann die Testbefehle vom Proxy-Server entgegen und steuert so die Anwendung.
Der Test selbst wird in Javascript formuliert und von einer im Proxy laufenden Javascript-Engine ausgeführt. Dafür kommt wie bei HtmlUnit die Rhino- Engine zum Einsatz, die neben Javascript auch die Ausführung beliebigen Java-Codes unterstützt. Dadurch ist ein umfassender Test des Gesamtsystems möglich, der neben dem Web-UI auch Server und Datenbank umfassen kann.
Sahi enthält einen Recorder, mit dem Testskripte beim Bedienen der Webanwendung aufgenommen werden können. Auch der Recorder benutzt den Proxy um Javascript-Code zu injizieren – diesmal um über zusätzliche Event-Handler die aufzuzeichnenden Useraktionen an den Proxy zu übermitteln.
Sahi-Testskripte sind gut lesbar und die gesamte Bandbreite der Javascript-Programmierung inklusive Fallunterscheidungen und Schleifen lässt sich nutzen, auch wenn man darüber diskutieren kann, ob komplex programmierte Testscripte guter Teststil sind. Elemente werden anhand einfacher Kriterien identifiziert, allerdings nichts so smart, wie es bei Wetator der Fall ist. Aus unserer Erfahrung kann Sahi gut mit Ajax-Events umgehen; explizites Warten ist unnötig. Allerdings kommt sich der injizierte Sahi-Javascript-Code öfter mal mit javascript-lastigen Webframeworks wie Vaadin oder Angular ins Gehege. So gibt es sowohl bei der Aufzeichnung als auch beim Abspielen Probleme, die von unzuverlässiger bis hin zu unmöglicher Testausführung reichen können.
Listing: Sahi-Script
_navigateTo("http://my-test-computer:8088/");
_setValue(_textbox("inputtext"), "Test Input");
_setValue(_textbox("substring"), "Test");
_click(_submit("Count Substrings"));
_click(_heading4("Test is contained 1 time(s) in Test Input"));
_setValue(_textbox("inputtext"), "Test Input Test");
_click(_submit("Count Substrings"));
_click(_heading4("Test is contained 2 time(s) in Test Input Test"));
Unser Fazit zu Sahi
- Robustheit: Weil die Suche in Sahi nur pseudo-intelligent funktioniert, ist noch eine eingeschränkte Abhängigkeit zu technischen Änderungen vorhanden. So muss der Test zumindest wissen, um welche Art des Elements es sich handelt, obwohl man bspw. sowohl auf einen Button als auch auf einen Link klicken könnte. Umgekehrt ist es aber egal, wo das klickbare Element sich im UI befindet, da in der Regel nicht mit Pfaden gearbeitet werden muss.
- Sensitivität: Sahi legt ebenso wie Wetator durch einfache Testbefehle und eine Suchfunktion, die sich an dem Bedienverhalten der Nutzer:innen orientiert, einen Fokus auf den fachlichen Test. Dadurch werden fachliche Änderungen im Test gut erkannt.
- Wartbarkeit: Durch die einfache Skriptsprache und die Abstraktion von konkreten Details der identifizierten Elemente sind Sahi-Skripte leicht lesbar und dadurch einfach zu warten. Allerdings ist aufgrund des eher eingeschränkten Testberichts nicht immer auf den ersten Blick ersichtlich, wo die eigentliche Fehlerursache liegt.
- Lesbarkeit: Die von Sahi generierten Testberichte sind kurz und wohl eher für Manager:innen gedacht. Tritt ein Fehler auf, ist nicht auf den ersten Blick ersichtlich, woran es lag, u. a. fehlen automatische Vorher/Nachher-Snapshots, die die Analyse erleichtern. Screenshots werden nur im Fehlerfall gemacht, so fehlen oft wichtige Informationen, insbesondere wenn die Ursache des Fehlers in vorangegangenen Schritten liegt.
Cypress – der Herausforderer
Kommen wir nun zum letzten und jüngsten Vertreter in unserem Quartett. Cypress selbst inklusive Testrunner sind Open Source, bezahlen muss man für das Hosting der Dashboard-Services und den Support. Für Open-Source-Projekte ist auch dies kostenlos.
Einen ganz anderen Architekturansatz haben die Entwickler von Cypress gewählt. Cypress selbst läuft im Browser und führt die zu testende Webanwendung in einem IFrame aus. So hat Cypress vollen Zugriff auf die Anwendung und kann sie sowohl steuern als auch beobachten. Einschränkungen bei der Kontrolle gibt es nur, wenn Teile der zu testenden Anwendung selbst in einem IFrame laufen, die Anwendung weitere Tabs oder Fenster öffnet oder domänenübergreifend agiert. Dann ist die Anwendung durch Cypress nicht mehr vollständig testbar, weil die Webanwendung aus dem ursprünglichen, von Cypress kontrollierten, Kontext ausbricht. Mit dieser Architektur hat Cypress wie Wetator Zugriff auf den gesamten DOM und auch auf die Shadow-DOMs. Eine Reihe von Erweiterungen ergänzen Cypress Funktionsumfang, z. B. die Unterstützung von Mock-Requests und Mock-Responses, um fehlende oder noch nicht implementierte Services zu simulieren oder die Schnittstellen kontrolliert zu bedienen.
Elemente werden durch Cypress auf unterschiedliche Art identifiziert z. B. per jQuery oder auch anhand des Textes eines Elements. In diesem Punkt verbessert sich die Funktionalität ständig, da eine Reihe von Projekten aktiv zur Weiterentwicklung von Cypress beitragen. Die Suche ist allerdings noch nicht mit der "Intelligenz" von Wetator vergleichbar.
Auch Cypress unterstützt implizites Warten, der Test ist dadurch sehr stabil und deutlich einfacher zu schreiben. Neben expliziten Asserts unterstützt Cypress auch implizite Asserts, d. h. wenn ein Element für eine Aktion gesucht wird, dann ist das Finden des Elements wie bei Wetator automatisch ein Assert.
Neben dem Testrunner stellt Cypress eigene Browser-Tools zur Verfügung, um das Entwickeln der Test zu unterstützen, u. a. um anzuzeigen, wie Cypress ein bestimmtes Element identifiziert. Allerdings sind die deutlich umfangreicheren Webtools der Browser aktuell noch empfehlenswerter.
Der Testreport besteht aus ‚Screenshots‘ der Schritte; wie bei einem Daumenkino kann man so den Testablauf nachvollziehen. Das jeweils benutzte Element wird im Report hervorgehoben, so dass sofort erkenntlich ist, wenn falsche Elemente identifiziert wurden. Im Gegensatz zu Wetator, das ebenfalls Vorher/Nachher-Snapshots erzeugt, sind diese jedoch interaktiver, z. B. wird direkt der Snapshot angezeigt, wenn man mit der Maus über eine Zeile im Testbericht fährt. Zusätzlich kann man für jeden Testschritt den entsprechenden Zustand des DOM untersuchen. Cypress kann einen Test auch als Video aufzeichnen, ein sehr nützliches Feature für den Continous-Build.
Cypress möchte sich so früh wie möglich in den Entwicklungsprozess integrieren; die Zielgruppe ist klar der Webentwickler. Die Tests werden in Javascript geschrieben, Cypress integriert sich in die Entwicklungsumgebung und erlaubt es, Tests direkt aus der Entwicklungsumgebung auszuführen oder sogar Test bei Codeänderungen automatisch zu starten. Durch das direkte Zusammenspiel von Entwicklung und Test erhofft man sich früheres und ausführlicheres Testen sowie eine Unterstützung des Entwicklungsprozesses selbst.
Cypress bietet auch Recorder als Browser-Plugin. Unsere Erfahrung mit den aufgezeichneten Skripten ist aber eher enttäuschend, diese lassen sich zumindest in den von uns getesteten Versionen der Recorder zwar aufzeichnen, aber nicht ohne Fehler abspielen und müssen nachbearbeitet werden.
Im Gegensatz zu allen anderen Testwerkzeugen unterstützt Cypress aktuell nur Chrome (und Abkömmlinge) und Firefox vollumfänglich, wobei dieser Nachteil aufgrund der Konsolidierung auf dem Browsermarkt immer weniger Relevanz hat.
Listing: Cypress-Script
describe('Simple Form Application Test', () => {
it('should calculate correctly', () => {
cy.visit('/');
cy.contains('Form Application');
cy.get('[data-test=inputInput]').type('Test Input');
cy.get('[data-test=substringInput]').type('Test');
cy.get('[data-test=resultDiv]').should('not.exist');
cy.get('[data-test=countButton').click();
cy.get('[data-test=resultDiv]').should('be.visible');
cy.get('[data-test=resultString]').contains("'Test" is contained 1 time(s) in "Test Input"'
);
cy.get('[data-test=inputInput]').type('Test');
cy.get('[data-test=resultDiv]').should('not.exist');
cy.get('[data-test=countButton').cLick();
cy.get('[data-test=resultString]').contains("'Test" is contained 2 time(s) in "Test Input Test"'
);
})
});
Unser Fazit zu Cypress
- Robustheit: Cypress ist nicht komplett unabhängig von technischen Änderungen, es hängt stark vom Tester ab, welche Art der Suche er nutzt. Die Suchkriterien, die Cypress selbst in seinen BrowserTools vorschlägt sind in der Regel nicht die besten.
- Sensitivität: Durch die vielen Arten der Asserts – explizite aber auch implizite – ist die Sensitivität zwar auch hier abhängig vom Tester, aber er wird sehr gut unterstützt, den Test sensitiv zu gestalten und falls erforderlich alle Aspekte der Anwendung zu testen.
- Wartbarkeit: Cypress merkt man sein relativ junges Alter deutlich an. Der Fokus liegt sehr stark auf modernen Javascript basierten Webanwendungen, die auf einem Web-Framework wie Angular oder React basieren [7]. Die nahtlose Integration in die Entwicklungsumgebung verbessert die Wartbarkeit zusätzlich.
- Lesbarkeit: Durch das Daumenkino, also den interaktiven Report, sind Tests gut lesbar und Fehler einfach nachvollziehbar.
Summa Summarum
Betrachten wir alle Architekturen noch einmal im Vergleich, so ist vom Steuern des Browsers per API über das Quasi-Kapern der Webanwendung bis hin zur Simulation des Browsers alles dabei. Und natürlich haben die verschiedenen Ansätze auch Einfluss auf die gebotenen Funktionalitäten der Tools. So bekommt man mit Selenium die technisch fast perfekte Steuerung des Browsers – die Tests müssen aber sehr nah an der Technik formuliert werden. Auf der anderen Seite bietet Wetator fachliche Tests ohne Berührungen mit der Technik, dafür muss man mit den Defiziten der Browsersimulation leben. Cypress bietet – insbesondere für die Entwicklung moderner Webapplikationen – aktuell einen guten Kompromiss; fokussiert sich aber eher auf die Entwickler als die Tester.
Neben den unterschiedlichen Architekturen spielt auch das Alter des Werkzeugs eine Rolle. Je älter der Ursprung des Werkzeugs, desto mehr musste es sich wandeln, um sich an neue Herausforderungen anzupassen. Testwerkzeuge verhalten sich in dem Punkt wie jedes andere Legacy-System. Anpassungen führen entweder zu einem Komplettumbau der zugrundeliegenden Architektur oder das Tool ist irgendwann neuen, moderneren Web-UIs nicht mehr gewachsen. Bei der Auswahl des passenden Werkzeugs ist deshalb nicht nur die Verbreitung ein Kriterium, sondern auch die Zielgruppe, die Handhabbarkeit und vor allem die technologische Basis der eigenen Webentwicklung. Selenium kommt in vielen unterschiedlichen Varianten daher und ist deshalb oft noch die vorrangige Wahl. Aber auch die Herausforderer lohnen mehr als einen oberflächlichen Blick. Für Fachanwender eignen sich Wetator und Sahi besonders, zeigen jedoch Schwächen, wenn moderne Single-Page-Anwendungen getestet werden sollen. Cypress legt den Fokus auf moderne Web-UIs und spielt dort seine Stärken klar aus.
Die vorgestellten Werkzeuge repräsentieren nur die Spitze der Testpyramide. Tests auf dieser Ebene sollten durch eine breite Basis von Unit- und Integrationstests ergänzt werden. Auch hier gibt es interessante Werkzeuge, die durchaus eine nähere Betrachtung verdienen. So gibt es bspw. mit JEST [8] einen Vertreter für den Test von Javascript-Anwendungen, mit dem die Interaktionslogik des UIs ohne die eigentliche View und damit ohne Browser getestet werden kann. Aber dies wäre ein anderes Kapitel im Feld des Tests von Web-Anwendungen.
- Selenium | Wetator | Sahi (eingeschränkte freie Version), Sahi (ältere Open-Source-Version) | Cypress
- WebDriver-API-Spezifikation
- PageObject-Pattern
- HtmlUnit
- Mozilla Rhino
- Spring MVC Test
- Angular | React
- JEST