Webanwendungen mit Cypress und
Cucumber testen

Schritt-für-Schritt Anleitung

End-to-End-Tests sind ein wichtiger Teil der Softwareentwicklung. Sie gehen noch einen Schritt weiter als Integrationstest und simulieren den tatsächlichen späteren Einsatz des Systems. Hat das Softwareprodukt eine Weboberfläche, wird häufig eine Benutzereingabe simuliert und eine entsprechende Reaktion erwartet. Wer solche End-to-End-Tests für Webanwendungen schreiben will, stößt unweigerlich auf Cypress, da es neben Selenium eines der bekanntesten Frameworks zum Testen von Webanwendungen ist.

Cypress-Tests bestehen aus mehreren aufeinanderfolgenden Schritten. Da in den Tests häufig die gleichen Aktionen ausgeführt werden, enthalten die Tests viele Duplikate. 

Hier kommt Cucumber ins Spiel: Es sorgt dafür, dass diese sich häufig wiederholenden Teile wiederverwendet werden können. Zudem kann Cucumber häufig verhindern, dass die Tests jedes Mal von Entwicklern manuell angepasst oder erweitert werden müssen, wenn Änderungen in der Webanwendung gemacht oder neue Funktionen entwickelt werden. Cucumber befähigt Tester, diese kleineren Anpassungen in überschaubarer Zeit selbst zu erledigen. Zu Beginn müssen die Entwickler noch viele sogenannte step definitions in Cypress neu implementieren, später kann der Tester diese selbstständig wiederverwenden und viel Entwicklungszeit sparen. 

Welche weiteren Vor- und Nachteile Cucumber in Verbindung mit Cypress hat und wie es aufgesetzt wird, wird in diesem Artikel genauer geschrieben. 

Grundfunktion

Wie in der Einleitung beschrieben, schreiben Testmanager sogenannte Szenarien, die in der sehr einfach verständlichen Sprache Gherkin ein Testszenario beschreiben, das getestet werden soll. Ein Beispiel:

				
					WENN ich mich als “Theo Tester” anmelde 
DANN sehe ich die Startseite 
* wird mein Nutzername angezeigt 
				
			

Hinweis: “*” bedeutet in diesem Fall “UND DANN”. Bei längeren Szenarien verbessert diese
Schreibweise die Lesbarkeit.

Diese Testszenarien werden beispielsweise in Jira definiert und verwaltet. Sie werden von einem Entwickler in step definitions implementiert und können von Testmanagern in beliebiger Kombination und Reihenfolge wiederverwendet werden. Daraus ergibt sich zu Beginn ein hoher Aufwand für den Entwickler und den Testmanager. Später jedoch, wenn
bereits viele step definitions implementiert wurden, hat der Entwickler, je nach Integration von Cypress, wenig bis gar keinen Aufwand mehr.

Vorteile

Die Vorteile liegen auf der Hand: Zum Ersten ist gut dokumentiert und für jeden einsehbar, welche Testfälle es gibt und welche Funktionen noch unzureichend getestet sind. Zum Zweiten wird die nötige Kommunikation zwischen Tester und Entwickler minimiert, da die einzelnen Testfälle sehr ausdrucksstark und leicht zu verstehen sind. Und zum Dritten wird
der Entwicklungsaufwand zunehmend weniger.

Dieses Setup ermöglicht außerdem den automatischen Import neuer Szenarien in der Buildpipeline und einen Export der entsprechenden Ergebnisse. Auf diese Funktionen wird fortlaufend nicht weiter eingegangen.

Setup

In diesem Artikel wird das Setup in einem Angular-Projekt beschrieben. Im ersten Schritt müssen die benötigten Abhängigkeiten installiert werden:

				
					npm install - -save-dev cypress @badeball/cypress-cucumber-preprocessor 
@cypress/webpack-preprocessor 
				
			

Um Cypress zu konfigurieren, wird die Datei cypress.config.js benötigt. Sie muss auf
der Root-Ebene neben beispielsweise der package.json angelegt werden. Der Inhalt
sollte in etwa so aussehen:

				
					const {defineConfig} = require("cypress");
const webpack = require("@cypress/webpack-preprocessor");
const preprocessor = require("@badeball/cypress-cucumber-preprocessor");

async function setupNodeEvents(on, config) {
  await preprocessor.addCucumberPreprocessorPlugin(on, config);
  on("file:preprocessor", webpack({
    webpackOptions: {
      resolve: {extensions: [".ts", ".js"],},
      module: {
        rules: [{
          test: /\.feature$/,
          use: [{
            loader: "@badeball/cypress-cucumber-preprocessor/webpack",
            options: config,
          },],
        },],
      },
    },
  }));
  return config;
}

module.exports = defineConfig({
  e2e: {
    specPattern: "**/*.feature",
    supportFile: false,
    video: false,
    defaultCommandTimeout: 10000,
    requestTimeout: 10000,
    retries: {runMode: 2}, // 3 runs in total        
  },
  setupNodeEvents,
}); 

				
			

Der untere Abschnitt kann nach Bedarf angepasst werden. Alle Konfigurationsparameter können Sie hier nachlesen. In der package.json muss folgende Konfiguration ergänzt werden:

				
					{
  ...
  "devDependencies": {
    ...
  },
  "cypress-cucumber-preprocessor": {
    "stepDefinitions": [
      "cypress/e2e/step_definitions/*.cy.js"
    ]
  }
}

				
			

Nun kann die erste .feature-Datei
{Projektverzeichnis}/cypress/e2e/{Feature}/testcase.cy.feature und
die step definitions
{Projektverzeichnis}/cypress/e2e/step_definitions/steps.cy.js
hinzugefügt werden. Die testcase.cy.feature-Datei könnte beispielsweise so
aussehen:

				
					#language: de

Funktionalität: Default
  Szenario: Korrekte Seite wird geladen
    Wenn ich die cypress website aufrufe
    Dann enthält die Überschrift “Kitchen Sink”

				
			

Während die Datei steps.cy.js folgendes enthält:

				
					import {Then, When} from "@badeball/cypress-cucumber-preprocessor";


When('ich die cypress website aufrufe', () => {
  cy.visit('https://example.cypress.io');
});

Then('enthält die Überschrift {string}', headline => {
  cy.get('h1').should('contain.text', headline)
}); 

				
			

Nun muss das Frontend lokal gestartet und Cypress mit folgendem Kommando aufgerufen
werden:

				
					npx cypress open 
				
			

In dem sich öffnenden Fenster muss “E2E Testing” und anschließend ein Browser ausgewählt werden, in dem der Test ausgeführt werden soll. Wenn alles richtig konfiguriert ist, wird im nächsten Fenster die .feature.-Datei angezeigt und mit einem Klick darauf der Test ausgeführt. Ein vollständig konfiguriertes Angular-Projekt ist hier hinterlegt.

Integration in CI/CD

Cypress bietet umfangreiche Integration in gängige CI/CD-Tools. In diesem Artikel wird die Integration in Github Actions beleuchtet. Cypress stellt für das automatisierte Ausführen der Tests die offizielle Github Action “cypress-io/github-action” zur Verfügung. Alle Konfigurationsparameter sind hier dokumentiert. Eine einfache Grundkonfiguration könnte beispielsweise so aussehen:

				
					jobs:
  e2e:
    name: Cypress Tests
    runs-on: ubuntu-22.04
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      
      - name: Setup node
        uses: actions/setup-node@v3
        with:
          node-version: 18
      
      - name: Install Dependencies
        run: npm install
      
      - name: Cypress run
        uses: cypress-io/github-action@v5
        with:
          browser: chrome
          record: false
          wait-on: ‘http://127.0.0.1:4201’
          install-command: npm install -g @angular/cli@14
        env:
          TZ: Europe/Berlin
      
      - name: Save screenshots folder
        uses: actions/upload-artifact@v3
        if: failure()
        with:
          name: cypress-screenshots
          path: cypress/screenshots
          retention-days: 5 

				
			

Nachteile

Es kann je nach Funktionsumfang und Alter des Frontends dazu kommen, dass für die eigentlich gleiche Funktion mehrere leicht unterschiedliche Implementierungen zum Einsatz kommen. Beispielsweise kann ein Button mehrere mit Bedingungen versehene
<div>Elemente enthalten oder eben nicht. Um solche Differenzen zu berücksichtigen, ohne die Testcases aus technischen Gründen unterschiedlich zu formulieren, müssen die einzelnen step definitions entsprechend flexibel gestaltet werden, um mit unterschiedlichen Implementierungen zurechtzukommen. Das erhöht den Entwicklungsaufwand und kann zu unerwarteten Problemen beim erstmaligen Ausführen neuer Testfälle führen.

Fazit

Cucumber und Cypress arbeiten sehr gut zusammen. Der anfangs investierte Aufwand rentiert sich vergleichsweise früh und führt zu besserer Testdokumentation, effizienterer Kommunikation zwischen Tester und Entwickler sowie schnellerer Erweiterung der Testfälle. Nachteilig ist die, ab einem gewissen Testumfang nötige, flexible Gestaltung der step definitions zu nennen.

Neugierig geworden?

Wir unterstützen Sie gerne dabei. Sprechen Sie uns einfach an.

Kontakt

Tom Schindler
Telefon: +49 (0)40 53302-0
E-Mail: Tom.Schindler@cimt-ag.de

cimtAcademy

Jetzt registrieren und keine Veranstaltungen mehr verpassen.​



    				
    					#language: de
    
    Funktionalität: Default
      Szenario: Korrekte Seite wird geladen
        Wenn ich die cypress website aufrufe
        Dann enthält die Überschrift “Kitchen Sink”
    
    				
    			
    Nach oben scrollen