Tool-Tipp

Cypress: Das beste Testing-Framework fürs Frontend?

(Foto: REDPIXEL.PL / Shutterstock)

Lesezeit: 7 Min. Gerade keine Zeit? Jetzt speichern und später lesen

Cypress ist ein Framework fürs Testing von Web-Anwendungen. Das Open-Source-Framework ähnelt auf den ersten Blick Selenium, ist aber fundamental anders und angeblich besser, einfacher und schneller. Wir haben einen genaueren Blick auf das Tool geworfen.

Ein Softwaretest prüft und bewertet Software auf Erfüllung der für ihren Einsatz definierten Anforderungen und misst ihre Qualität. Die gewonnenen Erkenntnisse werden zur Erkennung und Behebung von Softwarefehlern genutzt – sagt Wikipedia.

Nix mehr verpassen: Die t3n Newsletter zu deinen Lieblingsthemen! Jetzt anmelden

Drei verbreitete Arten von Tests sind:

  • Unit-Tests – kleine Tests, mit denen eine ganz spezifische Funktionalität getestet werden soll.
  • Integration-Tests – Tests, mit denen das Zusammenspiel verschiedener Funktionalitäten getestet werden soll.
  • End-to-End-Testing – Testing des gesamten Programmflows von Anfang bis Ende.

Zur Automatisierung von Tests gibt es eine Reihe von Frameworks; bekannte Namen sind zum Beispiel Mocha, Jasmine oder auch Jest. Viele davon basieren auf Selenium. Selenium ist so etwas wie ein Industriestandard. Für Entwickler, die über ausgereifte Programming- und Skriptingskills verfügen, bietet Selenium eine Flexibilität, die viele andere Tools vermissen lassen. Mit Selenium könnt ihr Tests in Java, Groovy, Python, C#, Ruby, PHP und Perl schreiben, die auf allen Systemen und in allen Browsern – Chrome, IE, Firefox und sogenannten Headless Browsern, also Browsern ohne grafische Benutzeroberfläche – laufen. Der Nachteil: Um mit Selenium vernünftig arbeiten zu können, braucht ihr schon wirklich ausgereifte Codingskills und müsst relativ viel Zeit investieren, bis ihr alles konfiguriert und aufgesetzt habt.

„Testing was broken“

Wollt ihr testen, ob eure App für den User so zu nutzen ist, wie ihr das vorgesehen habt, sind End-to-End-Tests das Mittel der Wahl. Sinnvoll verfasst, sind sie dem Nutzerverhalten am Nächsten – Probleme und Bugs in eurer App findet ihr am ehesten durch End-to-End-Tests. End-to-End-Tests sind aber auch kostspielig. Sie zu schreiben, dauert lange, sie auszuführen auch. Sie sind fragil und der Prozess wird von vielen Entwicklern als anstrengend empfunden. Aus diesen Gründen (Zeit, Ressourcen, Mühe) entscheiden sich viele Frontend-Entwickler beim Testing ihrer Applikationen für einzelne Unit- und Integration-Tests. Genau hier setzt Cypress an. Mit Cypress könnt ihr Tests für alles schreiben, was in einem (Chromium-basierten) Browser läuft. Das Framework will Setup, Schreiben, Durchführung und Debugging von End-to-End-Tests vereinfachen. Integration- und Unit-Tests sollen damit ebenfalls einfacher werden.

Cypress bedient sich bei anderen Frameworks

Cypress macht Anleihen bei Mochas bdd-Syntax – die sich für Unit- als auch Integration-Tests gleichermaßen eignet. Alle Tests, die ihr in Cypress schreiben werdet, basieren auf den folgenden Methoden:

describe(), context(), it(), before(), beforeEach(), afterEach(), after(),.only() und .skip()

Außerdem von Mocha übernommen: Der async-Support des Frameworks. Den haben die Cypress-Macher etwas modifiziert, alle Anpassungen sind jedoch komplett transparent. Während Mocha die Struktur stellt, kommen die Assertions in Cypress von Chai, die aufgrund der besonders guten Lesbarkeit und den On-Point-Fehlermeldungen in Cypress adaptiert wurden. Cypress schaut sich verschiedene jQuery-Chainer-Methoden von Chai-jQuery ab, stubs und spies von Sinon-Chai und kommt mit einer Reihe weiterer Library-Utilities.

 

Um auszuprobieren, ob Testing in Cypress wirklich so einfach ist, haben wir einen einfachen Login, bestehend aus Nutzername und Passwort, gebaut. Damit wir die Elemente innerhalb des DOM wiederfinden und über query-Selectoren darauf zugreifen können, sind beide, Nutzername und Passwort, mit einer ID versehen, #username respektive #password.

Los geht’s!

Starten könnt ihr einfach über den Terminal-Command npm install cypress –save dev, den Test-Runner für das grafische Interface könnt ihr mit npx cypress open öffnen oder (einfacher!) indem ihr den cypress:open -Command zur Script-Section eurer package.json hinzufügt.

Fügt cypress:open zur scripts-section eurer package.json hinzu. (Screenshot: t3n)

Wenn ihr Cypress das erste Mal startet, gibt euch das Framework mehrere Beispiel-Tests an die Hand. Die könnt ihr euch anschauen, um erstmal einen Überblick darüber zu bekommen, was mit Cypress alles geht. In /cypress/integration/[whatever you wanna call your-project].spec.js könnt ihr euren ersten Test-Test schreiben. Ein Test für eine Login-Funktion kann zum Beispiel so aussehen.

it("can find and type in email”, () => {           
cy.get(“#email”)                    
.type(user@t3n.de)                        
.should(“have.value”, user@t3n.de);            
});

Ziel des Tests ist es, sicherzustellen, dass der Nutzer einer Login-Page seine E-Mail-Adresse in den Input schreiben kann. Zuerst ziehen wir uns das Element über cy.get(„#email“) dann nutzen wir die .type-Methode, um den Test eine E-Mail-Adresse eintragen zu lassen. Im dritten Schritt stellen wir über .should sicher, dass die Annahme stimmt. Das ist ein ziemlich simpler Test, der aber gut illustriert, wie einfach das in Cypress funktioniert.

Wenn ein Nutzer unseres Logins sich mit einem falschen Passwort einloggt, soll er eine Failure-Message angezeigt bekommen. Ob das funktioniert, testen wir so:

“it will fail when valid user with invalid password”, () => {
cy.get(“#email”).type(“user@t3n”);
cy.get(“#password”).type(“12345”);
cy.get(“input[type=submit]”).click();
cy.get(“#login-message”).should(“have.text”, “Login failed”),
});

In diesem Test finden wir erst E-Mail- und Passwort-Formelemente, füllen sie – mit richtiger E-Mail-Adresse und falschem Passwort – aus und klicken den Submit-Button, dann finden wir das Element mit der id #login-message und überprüfen, ob die dann „Login Failed“ lautet. Durch die Aneinanderreihung derartiger kleiner Tests könnt ihr dann theoretisch eure ganze App von Anfang bis Ende durchtesten.

Ein wirklich großer Pluspunkt für Cypress ist, dass ihr dem Framework nicht sagen müsst, dass es auf Elemente warten soll – das macht es automatisch für euch. In einem Test, der zum Beispiel checkt, ob sich die URL nach Login dahingehend verändert, als dass die URL das Nutzerprofil beinhaltet –

cy.location("pathname").should("include", "/user/profile");

– wartet Cypress den Seitenwechsel ab und führt anschließend den Test aus. Klappt der Seitenwechsel nicht, beendet Cypress den Test einfach und ihr bekommt eine Fehlermeldung. Ihr müsst nirgends festlegen, dass Cypress warten soll, bis die Seite geladen ist, das passiert automatisch – das Tool nutzt standardmäßig einen Timeout, je nach Applikation. Die verschiedenen Timeouts findet ihr in der Konfigurationsdoku.

Bis hierhin und nicht weiter

Neben all diesen Vorteilen hat Cypress natürlich auch Nachteile. Cypress automatisiert euren Browser mit seiner framework-eigenen Architektur – und unterliegt einigen damit zwangsläufig einhergehenden Restriktionen:

  • Cypress ist kein Allzweck-Testing-Tool. Das Framework ist für eine Sache ausgelegt: End-to-End-Tests für eure App – und zwar während des Entwicklungsprozesses, nicht danach.
  • Commands in Cypress werden innerhalb eines Browsers ausgeführt. Das heißt, auch die Evaluation eures Test-Codes findet innerhalb des Browsers statt – in der Sprache des Web: JavaScript. Das macht die Kommunikation mit dem Backend – eurem Server oder der Database – etwas schwieriger. Ihr könnt aber zum Beispiel browser-kompatible Node-Module nutzen. Backend-Adapter für weitere Sprachen und Umgebungen sind bereits in Planung.
  • Die „Cypress runs inside the browser“- Geschichte bringt noch weitere Einschränkungen mit sich. Ihr könnt in Cypress nicht über mehrere Tabs testen – also ob beim Klick auf einen Link ein neuer Tab geöffnet wird. Tests, die natives Browser-Verhalten testen, braucht ihr aber eigentlich eh nicht – was der Browser macht, hat ja nichts mit eurer App zu tun. Stattdessen könnt und solltet ihr in diesem spezifischen Fall einfach das target=“blank“-Attribut testen, das Element, das das Öffnen des neuen Tabs triggert, zum Beispiel so:

cy.get(‘a[href=“/t3n”]‘).should(‘have.attr‘, ‘target‘, ‘_blank‘)

Der Grund: Cypress wechselt in jedem Test zur jeweiligen Domain. Die Origin-Policy der Browser gibt vor, dass Dinge wie localStorage, Service Worker, Cookies und viele andere API nicht über verschiedene Super-Domains geteilt werden dürfen. So wird sichergestellt, dass alles, was ihr auf einer Website tut, keinen Einfluss auf eine andere haben kann. Verschiedene Superdomains in einem jeweils eigenen Test zu besuchen, geht aber natürlich.

Als Faustregel gilt wie immer, dass ihr nicht versuchen solltet, in Cypress auf Drittanwendungen zuzugreifen. Ausnahme: Wenn ihr Authentifizierungslösungen wie OAuth oder Single-Sign-on nutzt, kommt ihr da wahrscheinlich nicht dran vorbei. Die Cypress-Docs bieten mehrere Guides mit ausführlichen Beschreibungen, was in solchen Fällen zu tun ist.

Fazit

Cypress läuft – nur falls ihr es bisher verpasst habt – innerhalb des Browsers. Das kommt mit einigen Restriktionen, die allerdings für den Hauptzweck des Ganzen – End-to-End-Testing von Anwendungen innerhalb eines Browsers – vollkommen okay sind. Cypress ist Open Source und innerhalb eines begrenzten Rahmens kostenlos. Das Framework ist einfach zu installieren, ihr braucht keine Dependencies, alles ist komplett modular. Testing steht mit Cypress nicht mehr am Ende der Entwicklung einer App, sondern wird Teil eures Workflows und findet währenddessen statt. Super für Nicht-Entwickler: Cypress kommt mit einem grafischen User-Interface, das ihr für eure Tests nutzen könnt– ihr könnt aber auch innerhalb eines Headless Browsers über die Kommandozeile testen. Wenn ihr schon andere Frameworks zum Test-Schreiben genutzt habt, werden euch viele Features von Cypress bekannt vorkommen. Aber auch wenn nicht, dürftet ihr euch relativ schnell einarbeiten können. Die Doku ist sehr ausführlich und wird ergänzt durch Grafiken, GIFs und Videos. Die Hauptschwierigkeit am Testing – sich sinnvolle Tests zu überlegen – bleibt zwar nach wie vor an euch hängen, alles, was sich drum herum befindet, macht Cypress euch aber einfacher.

Vielleicht auch interessant für euch: 

Meistgelesen

Bitte beachte unsere Community-Richtlinien

Wir freuen uns über kontroverse Diskussionen, die gerne auch mal hitzig geführt werden dürfen. Beleidigende, grob anstößige, rassistische und strafrechtlich relevante Äußerungen und Beiträge tolerieren wir nicht. Bitte achte darauf, dass du keine Texte veröffentlichst, für die du keine ausdrückliche Erlaubnis des Urhebers hast. Ebenfalls nicht erlaubt ist der Missbrauch der Webangebote unter t3n.de als Werbeplattform. Die Nennung von Produktnamen, Herstellern, Dienstleistern und Websites ist nur dann zulässig, wenn damit nicht vorrangig der Zweck der Werbung verfolgt wird. Wir behalten uns vor, Beiträge, die diese Regeln verletzen, zu löschen und Accounts zeitweilig oder auf Dauer zu sperren.

Trotz all dieser notwendigen Regeln: Diskutiere kontrovers, sage anderen deine Meinung, trage mit weiterführenden Informationen zum Wissensaustausch bei, aber bleibe dabei fair und respektiere die Meinung anderer. Wir wünschen Dir viel Spaß mit den Webangeboten von t3n und freuen uns auf spannende Beiträge.

Dein t3n-Team

6 Kommentare
Bla Blubb
Bla Blubb

„Das Framework ist für eine Sache ausgelegt: End-to-End-Tests für eure App – und zwar während des Entwicklungsprozesses, nicht danach.“

Und warum nicht danach? Was spricht dagegen, die Tests danach auszuführen? Welche Tests sollten stattdessen nach dem Entwicklungsprozess ausgeführt werden?

Antworten
Johannes Bayer
Johannes Bayer

Absolut toll: man kann cypress nicht ohne deren Cloud-Dashboard benutzen. Ein absolutes K.O.-Kriterium

Antworten
Daniel
Daniel

Ich nutze Puppeteer, lässt sich wunderderbar für End-to-End-Tests nutzen.

Antworten
Paul Werner
Paul Werner

Ich glaube, da hat sich ein Fehler im Code-Schnipsel eingeschlichen:
Statt
cy.get(“#email”)type.(“user@t3n”);
cy.get(“#password”)type.(“12345”);
Sollte es
cy.get(“#email”).type(“user@t3n”);
cy.get(“#password”).type(“12345”);
heissen.

Antworten
Falk
Falk

Ein super tool, lässt sich hervorragend in Verbindung mit docker nutzen. Drag and drop testing war ohne weiters machbar. Ganz feine Sache.

Antworten

Melde dich mit deinem t3n Account an oder fülle die unteren Felder aus.

Bitte schalte deinen Adblocker für t3n.de aus!

Hey du! Schön, dass du hier bist. 😊

Bitte schalte deinen Adblocker für t3n.de aus, um diesen Artikel zu lesen.

Wir sind ein unabhängiger Publisher mit einem Team bestehend aus 70 fantastischen Menschen, aber ohne riesigen Konzern im Rücken. Banner und ähnliche Werbemittel sind für unsere Finanzierung sehr wichtig.

Danke für deine Unterstützung.

Digitales High Five,
Luca Caracciolo (Chefredakteur t3n) & das gesamte t3n-Team

Anleitung zur Deaktivierung