#vuecember2020 #webentwicklung

Cypress

Cypress ist ein wundervolles Werkzeug zum Testen von vielschichtigen Vue-Komponenten, welche die Kapazität der Vue-Test-Library übersteigen. Wir geben einen Einblick, worauf es bei Cypress ankommt und wie ihr unerwartetes Verhalten bei euren ersten Integrationstests vermeidet.

Query-Selektoren und Variablendeklaration

Wenn ihr in der Vergangenheit schon einmal mit JavaScript oder gar jQuery zu tun hattet, verspürt ihr sicherlich gleich ein Verlangen, Selektoren wie

cy.get("[data-testid=mein-wichtiger-button]")

in eine Variable zu speichern.

Ihr solltet dieser Intention nicht folgen, denn Cypress-Funktionen sind asynchron. Ja, selbst cy.get! Benutzt stattdessen einen Alias, um auf eure gespeicherten DOM-Selektoren zurückzugreifen.

// Via .as('mainButton') können wir den Wert zwischenspeichern.
cy.get('select[data-testid=button-den-ich-immer-wieder-verwenden-möchte]').as('mainButton')

// Mit einem "@" können wir unseren zwischengespeicherten Wert aufrufen.
cy.get('@mainButton').scrollIntoView().click()

// ... weiterer Code

// Der Knopf wird nochmal gedrückt
cy.get('@mainButton').scrollIntoView().click()

Durch die Applikation navigieren

Verzicht ist nicht einfach, dennoch ist es sinnvoll cy.visit so weit wie möglich zu vermeiden. Denkt bei euren Tests wie ein Nutzer. Beginnt mit cy.visit('/') auf der Startseite eurer Applikation und bewegt euch über das Betätigen von Navigationspunkten mit cy.get("[data-testid=mein-navigationspunkt]").click() zu den verschiedenen Seiten. Das sorgt für ein passives Testen der entsprechenden Knöpfe und für ein verständliches Verhalten im Testablauf.

Stellt keine Eieruhr

Häufig kommt gerade bei den ersten Integrationstests der Gedanke cy.wait(10000) bei Schnittstellenabfragen zu verwenden. Auch hier gilt das Motto:

Denkt wie ein Nutzer.

Testet lieber mit cy.get("[data-testid=mein-lade-symbol]") auf einen sichtbaren Ladeindikator. Alternativ könnt ihr auch auf die Antwort eines XHR-Requests hören oder mit should("have.length.at.least", 1) auf einen gefüllten Warenkorb prüfen.

Das beschleunigt eure Tests! Während ihr mit cy.wait(10000) immer zehn Sekunden auf eine Antwort hofft. Könnt ihr mit cy.get('[data-testid=eintrag-im-warenkorb]', %7B timeout: 10000 %7D).should('have.length.at.least', 1) eine maximale Wartezeit einstellen, bis das Element im DOM verfügbar ist. Damit spart ihr jedes Mal die Differenz zwischen der Rückgabe der Anfrage und den zehn definierten Sekunden.

Kommandos hinzufügen

Erweitert den cy Kontext und stellt so nützliche Funktionen für alle Tests zur Verfügung. Als Beispiel für eine mögliche Erweiterung möchten wir euch die any Funktion vorstellen die uns häufig in unseren Integrationstests begleitet.

// Der erste Parameter definiert den Namen des Kommandos.
// Darauf folgt ein Options-Objekt, in welchem wir definieren,
// dass wir ein DOM-Element in unserer Funktion erwarten.
// Als letztes folgt die Hauptfunktion, in welcher ihr euer
// Kommando definiert.
Cypress.Commands.add('any', %7B prevSubject: 'element' %7D, (subject, size = 1) => %7B
  cy.wrap(subject).then((elementList) => %7B
    // Wir erstellen eine Kopie der übergebenen Elemente.
    const newElementList = [...elementList]

    // Danach mischen wir alle Positionen neu.
    newElementList.sort(() => Math.random() - 0.5)

    // Zum Schluss übergeben wir die gewünschte Elementlänge
    cy.wrap(newElementList.slice(0, size))
  %7D)
%7D)

Damit greifen wir in unseren Tests auf fünf zufällige Elemente zurück und können diese beispielsweise Klicken.

cy.get('[data-testid=meine-buttons]').any(5).click(%7B multiple: true %7D)

Zusammengefasst ist Cypress ein unerlässliches Werkzeug, welches wir bei sum.cumo, eine Tochter des israelischen Softwarekonzerns Sapiens, nicht missen möchten. Die Zeit lästiger manueller Tests ist lange vorbei, lang lebe die Automatisierung!