Testautomatisierung mit Cypress 13, Gherkin und Cucumber unter Anwendung des Page-Object-Modells

Cypress

 

In diesem Tutorial erstellen wir gemeinschaftlich ein kleines Beispielprojekt mit den folgenden Technologien und Methoden:

  • Node.js
  • npm
  • Visual Studio Code
  • Cypress
  • Gherkin
  • Cucumber
  • Page Object Model

 

Als Erstes werden die einzelnen Technologien erläutert, diese danach installiert und anschließend das Projekt aufgesetzt.

Das Tutorial ist primär für Anfänger konzipiert, wobei jeder Teil bei bereits vorhandenem Wissen,
einfach übersprungen, und zum nächsten Teil übergegangen werden kann.

Erläuterung verwendeter Technologien

 

Node.js

 

Node.js ist eine plattformunabhängige Open-Source Laufzeitumgebung für die Sprache Javascript (äquivalent zu Java Virtual Maschine für Java), um diese außerhalb des Webbrowsers nutzen zu können. Für unser Projekt wird diese benötigt, da Cypress auf Node.js und Javascript basiert.

 

npm

 

Wie der Name Node Package Manager bereits verrät, handelt es sich hierbei um einen freien Paketmanager, basierend auf der Javascript-Laufzeitumgebung Node.js. Mit diesem kann man einfach und bequem die für das eigene Projekt notwendigen Module (im folgenden als Synonym für Pakete genutzt) installieren und verwalten. Des Weiteren fungiert npm auch als CLI (Kommandozeilenprogramm), um Module ausführen zu können.

Mit dem Befehl:

npm install [Parameter] <packagename>

können benötigte Module installiert werden.

  • Parameter: Werte die die Installation verändern, zum Beispiel -g für eine globale Installation.
  • packagename: Der Name des zu installierenden Moduls.

 

Ein wichtiger Aspekt für die Entwicklung ist, das Module jeweils global oder lokal installiert werden können.

Lokal

npm install Paketname

Ein Modul wurde nur für das Verzeichnis installiert, in welchem der Paketmanager aufgerufen wurde (Wurzelverzeichnis des Projektes) und kann daher nur in diesem genutzt werden. Man nutzt dies, wenn man spezielle Module nur für ein Projekt benötigt, oder wenn man verschiedene Versionen desselben Moduls für unterschiedliche Projekte nutzt. Die Module werden dann in den Ordner node_modules des Projektes installiert.

 

Global

npm install -g Paketname

Ein Modul wird Global auf dem Rechner zur Nutzung für alle Projekte installiert. Wo diese Module installiert worden hängt vom System ab.

 

 

Welche Module und wo diese installiert sind, können wir uns im Terminal anzeigen lassen, dabei kann zwischen lokalen und globalen Modulen unterschieden werden:

npm list

zeigt alle für das Verzeichnis / Projekt lokal installierten Module an, und muss auch im Projektordner ausgeführt werden.

 

npm list -g

zeigt alle global installierten Module an, und kann überall ausgeführt werden.

 

Cypress

Cypress ist ein Frontend-Testautomatisierungstool für Webanendungen, programmierbar in Javascript und Typescript.
Näheres über Cypress erfahren wir hier: https://www.testautomatisierung.org/cypress/

 

Gherkin

Gherkin ist eine Beschreibungssprache zur effektiven Gestaltung von Anforderungen im Behavior-Driven-Development Stil.
Näheres über Cypress erfahren wir hier: https://www.testautomatisierung.org/lexikon/gherkin/

 

Cucumber

Ein plattformunabhängiges Framework, das geschriebene Anforderungen in Gherkin in automatisierte Tests für verschiedene Programmiersprachen wie Java, Ruby, C++ oder JavaScript umsetzt.
Näheres über Cucumber erfahren wir hier: https://www.testautomatisierung.org/lexikon/cucumber/

 

Page Object Model (POM)

Das Page Object Model (POM) ist ein bewährtes Entwurfsmuster in der Testautomatisierung, das darauf abzielt, gemeinsame Interaktionen mit einer Webanwendung, wie etwa einen Login-Vorgang, zu abstrahieren.

Hauptziel des POM ist die Steigerung der Wartbarkeit, Lesbarkeit und Erweiterbarkeit von Testskripten. Durch die klare Strukturierung von Seitenobjekten werden wiederkehrende Aktionen und Elemente effizient organisiert und können leicht in verschiedenen Testszenarien wiederverwendet werden.

 

Installation verwendeter Technologien

 

Node.Js Installieren unter Windows

 

Wir gehen auf die Seite von Node.js (https://nodejs.org/en/download) und downloaden die Version unter Recommended For Most Users.

 

 

Folgt dem Installationsmenü, beachtet dabei, dass im Schritt Custom Setup der Punkt Add to PATH ausgewählt ist.

Das ist wichtig, da dies node.js unter Windows  in einer fest durch einen Standard definierten globalen Systemvariable speichert, und somit jedes Programm welches auf Node.js zugreifen möchte, dieses auch findet.

Nach der Installation führen wir eine Command Promt (Windows Kommandozeile) aus, indem wir cmd in das Windows-Suchfeld eingeben und das Programm Command Prompt
aus den Vorschlägen anklicken.

In der Commandozeile überprüfen wir ob Node.js korrekt installiert mit dem Befehl:

node -v

wobei -v für Version steht.

Die angezeigt Version sollte der entsprechen, welche wir installiert haben.

Visual Studio Code installieren unter Windows

Wir gehen auf die Seite von Visual Studio Code: https://code.visualstudio.com/, downloaden die Version unter Download for Windows – Stable Build, und folgen dem Installationsmenü.

 

 

 

Projekt aufsetzen

 

Virtual Studio Code vorbereiten

Projektordner erstellen

Wir erstellen einen Ordner mit dem Namen unserer Wahl und öffnen anschließend Visual Studio Code.
Den Ordner in VS Code öffnen wir über  File -> Open Folder und wählen den von uns benannten Ordner aus.

 

Erweiterung(Plugin) installieren

Um effektiv mit Gherkin und Cucumber unter VS Code arbeiten zu können, installieren wir in VS Code das Plugin: Cucumber (Gherkin) Full Support.
Es ermöglicht, die in Gherkin definierte Beschreibungssprache in den von uns erstellten Feature-Dateien farblich hervorzuheben.

Dazu gehen wir in VS Code links auf das Symbol Extensions, geben in die Suchleiste Cucumber ein, und installieren das im Bild gezeigte Plugin.

 

 

 

Projekt initialisieren

Um ein Projekt mit node.js zu initialisieren, nutzen wir den Paketmanager npm. Wir nutzen den Befehl npm init -y, wobei das -y ein zusätzlicher Parameter ist, wodurch npm das Projekt mit Defaultwerten aufsetzt, wie im folgenden Bild in der Ausgabe im Terminal zu sehen ist.

 

Was hier ausgegeben wird, ist die von npm inital erstellte package.json.

 

Diese ist das Herzstück des Projektes und definiert die benötigten Abhängigkeiten.
Sie ist das Äquivalent zur pom – Datei aus dem Java – Maven Umfeld.

  • name:              Offizieller Name des Projektes
  • version:          Aktuelle Version des Projektes
  • description:  Beschreibung des Projektes
  • main:               Der Einstiegspunkt des Hauptprogramms des Projektes
  • scripts:            Hier können Scripts zur einfacheren Ausführung mit NPM eingefügt werden
  • keywords:      Wörter die das Modul beschreiben, mit denen das Modul bei Veröffentlichung durch Suchbegriffe gefunden werden kann
  • author:            Der Entwickler des Projektes
  • license:            Die Lizenz unter der die Software betrieben werden soll, default Open-Source-Lizenz des ISC (Internet System Consortium)

 

Die package.json finden wir danach in unserem Projektordner und diese sollte der Ausgabe im Terminal entsprechen:

{
  "name": "cypress_cucumber_gherkin_pageobjects",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

 

Module installieren

Im folgenden installieren wir zunächst alle für das Projekt erforderlichen Module

 

Cypress 13

Cypress installieren wir mit npm im Terminal über den Befehl:

npm install cypress --save-dev

als devDependency.

 

Als nächstes initialisieren wir Cypress indem wir mit dem Befehl:

npx open cypress

Cypress öffnen und unsere Grundstruktur für das Testprojekt vorbereiten. Hier bietet uns Cypress an, Projektstrukuren für E2E oder Component Testing aufzusetzen.
Wir klicken auf E2E und anschließend auf Continue.

 

Im folgenden Fenster können wir uns aussuchen welchen Browser wir nutzen wollen, und klicken dann auf Start E2E Testing in Chrome.

Es öffnet sich ein Chromebrowser in welchem der Specrunner aufgerufen wird.
Dort gibt es die 2 Möglichkeiten:

 

  • Scaffold example specs: Beispieltests von Cypress generieren lassen um zu verstehen wie Cypress funktioniert
  • Create new spec: Struktur für eigene E2E Tests erstellen lassen

 

Wir klicken auf Create new spec und anschließend auf Create spec um uns von Cypress den ersten Tests erstellen zu lassen.

 

 

In Cypress sollte das so aussehen:

 

 

 

Und in VS Code haben wir dann die folgende Struktur:

 

 

Anschließend schließen wir den Specrunner zunächst.

Wir gehen in VS Code und löschen den von Cypress erstellten spec.cy.js unter  cypress/e2e.

 

Cucumber

Cucumber für Cypress installieren wir über npm im Terminal über den Befehl:

npm install --save-dev cypress-cucumber-preprocessor

Bei dem cypress-cucumber-preprocessor handelt es sich um ein kleines Program, welches vor dem Start (pre) von Cypress, die von uns geschriebenen Feature Files und Step Files miteinander verbindet, damit wir diese dann im Cypress Specrunner nutzen können. (Dies entspricht der Runnerklasse aus dem Java Cucumber  Umfeld). Da wir unsere Feature und Step Files frei in einem Ordner im Projektordner anlegen können müssen wir dem cypress-cucumber-preprocessor Modul mitteilen, an welcher Stelle die Dateien zu finden sind.

 

Dafür erstellen wir uns zunächst 2 neue Ordner features und steps unter cypress/e2e/.
Für Cypress können wir die cypress.config.js nutzen um eine Verbindung zwischen den features, steps und dem cypress specrunner zu erreichen.

 

Dafür schreiben wir die cypress.config.js wie folgt um:

const { defineConfig } = require("cypress");                                     (1)
const cucumber = require("cypress-cucumber-preprocessor").default;               (2)

module.exports = defineConfig({                                                  (3)   
  e2e: {
    specPattern: "**/*.feature",                                                 (4)
    setupNodeEvents(on, config) {
      on("file:preprocessor", cucumber());                                       (5)
    },
  },
});
  • (1) defineConfig aus cypress wird importiert um es für unsere Zwecke umschreiben zu können
  • (2) cucumber wird aus dem Modul cypress-cucumber-preprocessor geladen und als Konstante gespeichert
  • (3) defineConfig wird mit Werten befüllt und anschließend exportiert
  • (4) Das Pattern wird definiert, nach welchem die Feature Files gesucht, und an den cypress-cucumber-preprocessor übergeben werden
  • (5) Der cypress-cucumber-preprocessor wird aktiviert, und cucumber() gestartet, wenn Cypress startet, dies wird auch hook genant.

 

 

Des Weiteren müssen wir in unserer package.json, also der Konfigurationsdatei unseres Projektes, die folgenden Zeilen hinzufügen:

  "cypress-cucumber-preprocessor": {                                 
    "nonGlobalStepDefinitions": false,                          (1)
    "step_definitions": "cypress/e2e/steps"                     (2)
  }
}
  • (1) An dieser Stelle können wir dem cypress-cucumber-preprocessor mitteilen, ob die steps, global gesucht werden sollen, in unserem Fall stellen wir das aus
  • (2) Mit dieser Zeit definieren wir den Ordner, an welchem sich unsere step files befinden werden

 

Damit haben wir alle Schritte durchgezogen, um unsere feature files und step files miteinander zu verbinden, den cypress-cucumber-preprocessor
vor dem Ausführen von Cypress zu starten und die feature files als spec files im Cypress specrunner nutzen zu können.

 

Durchführung des Projektes

 

Die Durchführung dieses Beispielprojektes erfolgt nach den Prinzipien moderner Qualitätssicherung:

  1. Anforderungsanalyse nach BDD und Ableitung entsprechender Features mit Gherkin
  2. Technische Analyse der geplanten Umsetzung, aus welcher wir die PageObjects für die Testautomatisierung ableiten und erstellen
  3. Erstellen der Steps aus den Feature Files mit der Testautomatisierungstechnologie (hier Playwright), in der entsprechenden Sprache (hier TypeScript)
    unter Verwendung unserer gut wart- und wiederverwendbaren PageObjects.

Als Beispielwebanwendung nutzen wir den Login der Simplytest eigenen Bankingdemoanwendung unter : http://testorbit.germanywestcentral.cloudapp.azure.com:4200.

Wir gehen für die Übung davon aus, dass wir mit dem gesamten Team in der Three Amigos Session (Näheres finden wir hier: 3 Amigos) die folgenden Scenarios für das Feature: UserLogin ausgearbeitet haben.

 

Feature File

Dafür erstellen wir uns die Datei UserLogin.feature im Ordner cypress/e2e/feature.
In diese schreiben wir das folgende Scenario:

 

Feature: UserLogin                                                                    (1)
  Scenario Outline: Ein Nutzer kann sich mit korrekten Nutzerdaten einloggen          (2) 
    Given Der Nutzer ist auf der Startseite                                           (3)
    When Der Nutzer gibt korrekte Daten für '<Username>' und '<Password>' ein
    Then Der Nutzer wird korrekt eingeloggt

    Examples:                                                                         (4)
      | Username | Password |  
      |  00001   |   demo   |                                                         (5)

 

  • (1) Der Name des zu testenden Features
  • (2) Die Beschreibung des Szenarios. Outline ist ein Befehl, um die Daten aus der Examples: Liste dem Step übergeben zu können.
  • (3) Die umzusetzenden Steps in der Feature File
  • (4) Examples: Ein Tabelle bei der die Werte unter den Headervariablen direkt von Cucumber auf die entsprechenden Variablen in den Steps abgebildet werden. Hier werden Username auf ‚<Username>‘ und Password auf ‚<Password>‘ abgebildet. Cucumber führt die Szenarien dann für jeden Datensatz einmal aus.
  • (5)  Beispieldatensatz: Username = 00001 , Password=demo.

 

 

PageObject mit Cypress in Javascript

Nun analysieren wir die Seite der Webanwendung, auf der sich der Login befindet,und überlegen uns welche der Elemente wir für das PageObject LoginPage benötigen.
Dabei ist zu beachten, dass wir in das PageObject LoginPage nur die Elemente aufnehmen, welche nur auf dieser Seite vorhanden sind.
Wenn wir nun die Seite betrachten:

 

 

sehen wir, dass wir für unsere Steps aus dem Feature UserLogin die Elemente:

  • Inputfeld: Username (Nutzernamen eingeben)
  • Inputfeld: Password (Password eingeben)
  • Button: Login (Login Button drücken)

benötigen werden.

 

Wir schauen uns die Seite genauer an und sehen, dass alle Felder jeweils ein Attribut id und data-test besitzen.
Mit Cypress können wir die Elemente jeweils wie folgt ansprechen:

 

id

  • Inputfeld: Username  => cy.get(‚#contract_input‚)
  • Inputfeld: Password   => cy.get(‚#password_input‘)
  • Button: Login               => cy.get(‚#login_button‚)

data-testid

  • Inputfeld : Username  => cy.get(‚[data-testid=“contract_input“]‘)
  • Inputfeld : Password   => cy.get(‚[data-testid=“password_input„]‘)
  • Button : Login               => cy.get(‚[data-testid=“login_button„]‘)

da data- tags am meisten isoliert sind, und hier der tag sogar eindeutig als data-testid benannt wurde, nehmen wir dieses Attribut als Identifier.

 

Wir erstellen die Klasse LoginPage mit den 3 Methoden:

class LoginPage{

setUsername(username){                           
        cy.get('[data-testid="contract_input"]')            (1)
        .clear()                                            (2)
        .type(username);                                    (3)
    };

 setPassword(password){
        cy.get('[data-testid="password_input"]')
        .clear()
        .type(password);
    };

 clickLoginButton(){
        cy.get('[data-testid="login_button"]')
        .click();                                           (4)
    };
}

export default LoginPage;                                   (5)
  • (1) Es wird das Objekt des Inputfeldes Username gesucht
  • (2) Es werden alle Daten aus dem Inputfeld gelöscht, welche eventuell vom Browser automatisch eingetragen wurden (Best Practice)
  • (3) Es wird der übergebene Username eingetragen
  • (4) Der Button für den Login wird geklickt
  • (5) Es wird die Klasse LoginPage mit dem Defaultkonstruktor exportiert, damit diese später in unseren Tests genutzt werden kann

 

Stepfiles

Mit unserem PageObject LoginPage haben wir nun die Grundlage um unsere Steps umzusetzen.
Im Ordner pages erstellen wir eine Datei mit dem Namen: LoginPage.cy.js.
cy.js ist wichtig damit Cypress die Steps als Specs (Cypress Name für Testsuites) erkennt, diese dann vom
cypress-cucumber-preprocessor verarbeitet und anschließend im Specrunner genutzt werden.
Wir müssen dem cypress-cucumber-preprocessor mitteilen welche Funktionen er auf welche Steps, in den Feature Files abbilden muss.
Das gelingt in Cypress unter anderem nach den folgenden Prinzipien:

 

als arrow Funktion:

GherkinCommand des Steps(Stepsatz, () => {
Funktionsrumpf
});

als anonyme Funktion:

GherkinCommand des Steps(Stepsatz, function() {
Funktionsrumpf
});

 

Wir nutzen die arrow Funktion, weshalb die Steps wie folgt aussehen:

import { Given, When, Then} from "cypress-cucumber-preprocessor/steps"                              (1)
import LoginPage from "../pages/LoginPage";                                                         (2)

const loginPage = new LoginPage();                                                                  (3)

/*          Given           */

Given("Der Nutzer ist auf der Startseite", () => {                                                  (4)
    cy.visit("http://testorbit.germanywestcentral.cloudapp.azure.com:4200");
});

/*          When           */

When("Der Nutzer gibt korrekte Daten für {string} und {string} ein", (username, password) => {      (5)
    loginPage.setUsername(username);                                                                (6)
    loginPage.setPassword(password);
    loginPage.clickLoginButton();
});

/*          Then           */

Then("Der Nutzer wird korrekt eingeloggt", () => {                                                  (7)
    cy.title().should('eq',"BankingSoftwareFrontEnd");
});
  • (1) Es werden die Gherkin Step Befehle aus dem Modul: cypress-cucumber-preprocessor importiert
  • (2) Die LoginPage wird als Klasse importiert
  • (3) Ein neues Objekt der Klasse: LoginPage wird intialisiert
  • (4) Der Step Given Der Nutzer ist auf der Startseite wird implementiert
  • (5) Der Step When Der Nutzer gibt korrekte Daten für ‚<Username>‘ und ‚<Password>‘ wird implementiert. Wir sehen hier, dass die Werte ‚<Username>‘ und ‚<Password>‘ aus den Step files durch den entsprechenden Datentyp, welcher an die Methode übergeben werden soll, ersetzt werden muss. In diesem Fall durch einen String: {string}
  • (6) Die Methoden aus dem Pageobject LoginPage werden genutzt um den Step abzubilden
  • (7) Der Step Then Der Nutzer wird korrekt eingeloggt wird implementiert, wir überprüfen hier, dass der Titel der Seite nach dem Login korrekt ist

 

Ausführung und Abschluss

 

Nun können wir unsere Tests mit dem Cypress specrunner ausführen.

Dafür öffnen wir ein neues Terminal und geben den folgenden Befehl:

npx cypress open

ein, und rufen über E2E Testing und Start E2E Testing in Chrome den Specrunner auf.

 

Wir sehen jetzt unser Feature UserLogin.feature als Spec in Cypress, und können dieses genauso ausführen wie einen „normalen“ Testspec von Cypress.

 

 

 

Das Ergebnis sieht dann wie folgt aus:

 

 

 

Herzlichen Glückwunsch, unsere ersten Tests mit Cypress und Cucumber waren erfolgreich!

 

 

 

 

 

 

 

 

0 Kommentare

Hinterlasse einen Kommentar

An der Diskussion beteiligen?
Hinterlasse uns deinen Kommentar!

Schreibe einen Kommentar

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