CI/CD-Pipelines mit Cypress und GitHub Actions automatisieren

CI/CD-Pipelines erleichtern die Softwarebereitstellung, indem sie Code-Integration, Validierung und Deployment automatisieren. Die Einbindung von End-to-End-Tests (E2E) stellt sicher, dass Änderungen wie vorgesehen in realen Nutzungsszenarien funktionieren. Durch die Kombination von GitHub Actions mit Cypress lassen sich Testabläufe automatisieren, manuelle Arbeitsschritte reduzieren und schnellere Rückmeldungen erzielen.

Diese Anleitung zeigt, wie man Cypress-basierte CI/CD-Pipelines mit GitHub Actions einrichtet. Du erstellst eine Beispielanwendung mit Next.js und konfigurierst automatisierte Tests mit Cypress.

Voraussetzungen

Stelle sicher, dass folgende Bedingungen erfüllt sind:

  • Erstelle ein GitHub-Repository für dein Projekt, z. B. cypress-dev-test, und richte deine Workflows ein.
  • Verwende ein Linux-System wie Ubuntu 24.04.
  • Installiere und initialisiere Git auf deinem lokalen Rechner.
  • Verwende einen aktiven Slack-Workspace, um Benachrichtigungen zu Testläufen zu erhalten.

Ein Beispielprojekt mit Next.js einrichten

Next.js ist ein Framework auf Basis von React, das Funktionen wie statische Generierung, serverseitiges Rendering und API-Routen unterstützt. Befolge die folgenden Schritte, um ein Beispielprojekt für Cypress-Tests zu erstellen:

Paketindex aktualisieren

Node.js und NPM installieren

$ sudo apt install nodejs npm -y

Node.js-Version prüfen

Die Ausgabe sollte Version 18.x oder höher anzeigen:

Falls eine ältere Version installiert ist, folge der offiziellen Anleitung zur Installation von Node.js und NPM unter Ubuntu 24.04.

Zum Home-Verzeichnis wechseln

Ein neues Next.js-Projekt erstellen

$ npx create-next-app@latest my-project

Drücke Enter, um die Standardpakete zu akzeptieren und auf die Setup-Fragen zu antworten.

Beispielausgabe nach erfolgreichem Setup:

added 379 packages, and audited 380 packages in 1m
147 packages are looking for funding
found 0 vulnerabilities

Success! Created my-project at /root/example-project/my-project

Zum Projektverzeichnis wechseln

Verzeichnisstruktur anzeigen

Die erwartete Ausgabe sieht wie folgt aus:

app  next.config.ts  node_modules  package-lock.json  public
eslint.config.mjs  next-env.d.ts  package.json  postcss.config.mjs  README.md  tailwind.config.ts  tsconfig.json

Port 3000 in der Firewall freigeben

Falls UFW nicht installiert ist, verwende diesen Befehl:

$ sudo apt install ufw -y && sudo ufw allow ssh

UFW-Konfiguration neu laden

Entwicklungsserver starten

Beispielausgabe:

▲ Next.js 15.1.6 (Turbopack)
- Local: http://localhost:3000
- Network: http://:3000

✓ Starting...
✓ Ready in 826ms
○ Compiling / ...
✓ Compiled / in 1906ms

Nutze die öffentliche IP deines Servers im Browser, um die Anwendung aufzurufen: http://<SERVER-IP>:3000.

Drücke Strg + C, um den Server zu stoppen.

Kontaktformular für Testzwecke erstellen

Mit diesem Formular lässt sich die Benutzerinteraktion simulieren, um visuelle Probleme über End-to-End-Tests aufzudecken. Es enthält Felder für Vorname, Nachname, E-Mail-Adresse und Nachricht. Die eingegebenen Daten werden in der Konsole protokolliert.

Projektpfad prüfen

Die Ausgabe sollte etwa wie folgt aussehen:

/home/linuxuser/my-project

Originaldatei sichern

$ mv app/page.tsx app/page.tsx.ORIG

Datei mit Editor öffnen

Code für Kontaktformular einfügen

„use client“;
import { useState } from „react“;

export default function Contact() {
const [data, setData] = useState({
firstName: „“,
lastName: „“,
email: „“,
message: „“,
});

const handleChange = (event: React.SyntheticEvent) => {
const target = event.target as HTMLInputElement;
setData((prev) => ({ …prev, [target.name]: target.value }));
};

const handleSubmit = async (event: React.SyntheticEvent) => {
event.preventDefault();
console.log(„Form Submitted:“, data);
setData({ firstName: „“, lastName: „“, email: „“, message: „“ });
};

return (
<main className=“w-[100%] h-[100%] absolute top-0 left-0 bg-[#8dd0fa] flex flex-col items-center justify-center“>
<h1 className=“text-[26px] font-bold mb-4 text-black uppercase“>
CONTACT US
</h1>
<form
onSubmit={handleSubmit}
className=“w-[450px] flex flex-col items-center text-black“
>
<div className=“w-full flex justify-between my-2″>
<input
type=“text“
name=“firstName“
placeholder=“First Name“
onChange={handleChange}
value={data.firstName}
required
className=“outline-none w-[48%] h-10 p-2 rounded shadow-sm“
/>
<input
type=“text“
name=“lastName“
placeholder=“Last Name“
onChange={handleChange}
value={data.lastName}
required
className=“outline-none w-[48%] h-10 p-2 rounded shadow-sm“
/>
</div>
<input
type=“email“
name=“email“
placeholder=“Email“
onChange={handleChange}
value={data.email}
required
className=“outline-none w-full h-10 p-2 rounded my-2 shadow-sm“
/>
<textarea
name=“message“
id=“message“
placeholder=“Message“
rows={5}
onChange={handleChange}
value={data.message}
required
className=“outline-none w-full p-2 rounded my-2 shadow-sm“
/>
<button type=“submit“ className=“bg-black text-white m-2 w-full py-2″>
Submit
</button>
</form>
</main>
);
}


Speichere die Datei und beende den Editor.

Kontaktformular anzeigen und Server im Hintergrund starten

Das erstellte Kontaktformular enthält mehrere Felder zur Eingabevalidierung und simuliert reale Benutzerinteraktionen.

Starte den Entwicklungsserver im Hintergrund, damit die Anwendung auf Port 3000 erreichbar bleibt:

Öffne die Adresse http://<SERVER-IP>:3000 im Browser, um das Formular aufzurufen und sicherzustellen, dass es korrekt angezeigt wird.

Cypress installieren und konfigurieren

Folgende Schritte zeigen dir, wie du Cypress für End-to-End-Tests lokal einrichtest.

Abhängigkeiten installieren

$ sudo apt install libgtk2.0-0t64 libgtk-3-0t64 libgbm-dev libnotify-dev libnss3 libxss1 libasound2t64 libxtst6 xauth xvfb -y

Cypress als Dev-Abhängigkeit installieren

$ npm install cypress --save-dev

Cypress initialisieren

Folge im Cypress-Launchpad diesen Schritten:

  • Klicke auf Continue, wenn die Release-Information erscheint.
  • Wähle E2E Testing.
  • Stelle sicher, dass Konfigurationsdateien erstellt werden, und klicke erneut auf Continue.
  • Wähle deinen bevorzugten Browser und klicke auf Start E2E Testing.
  • Klicke auf Create new spec, um eine neue Testdatei zu erstellen.
  • Benenne die Datei in contact.cy.ts um.
  • Bestätige nach der Erfolgsmeldung mit Okay, run the spec.

Projektdateien prüfen

Erwartete Ausgabe:

app      cypress.config.ts  next.config.ts  node_modules  package-lock.json   public     tailwind.config.ts
cypress  eslint.config.mjs  next-env.d.ts   package.json  postcss.config.mjs  README.md  tsconfig.json

Cypress-Konfiguration bearbeiten

Bearbeite die Konfigurationsdatei und ergänze die Basis-URL für die Tests:

Füge in der e2e-Konfiguration folgende Zeile hinzu:

baseUrl: process.env.BASE_URL || 'http://localhost:3000',

Beispiel für vollständige Konfiguration

import { defineConfig } from "cypress";

export default defineConfig({
  e2e: {
    baseUrl: process.env.BASE_URL || 'http://localhost:3000',
    setupNodeEvents(on, config) {
      // implement node event listeners here
    },
  },
});

Diese Konfiguration sorgt dafür, dass alle Tests dieselbe Basis-URL nutzen und keine URLs hartcodiert werden müssen.

Einen Cypress-Test erstellen

Gut strukturierte Tests bestehen aus den drei Phasen: Vorbereitung, Aktion und Überprüfung. Im folgenden Beispiel wird das Formular geöffnet, mit Testdaten gefüllt, abgeschickt und die Konsolenausgabe überprüft.

Standard-Testdatei sichern

$ mv cypress/e2e/contact.cy.ts cypress/e2e/contact.cy.ts.ORIG

Neue Testdatei erstellen

$ nano cypress/e2e/contact.cy.ts

Cypress-Testcode einfügen

describe('Contact Page Tests', () => {
  beforeEach(() => {
    cy.visit('/');
  });

  it('Submits the form successfully', () => {
    cy.window().then((win) => {
      cy.spy(win.console, "log").as("consoleLog");
    });

    cy.get('input[name="firstName"]').type('John');
    cy.get('input[name="lastName"]').type('Doe');
    cy.get('input[name="email"]').type('john_doe@example.com');
    cy.get('textarea[name="message"]').type('This is a test message.');
    cy.get('button[type="submit"]').click();

    cy.get("@consoleLog").should("be.calledWith", "Form Submitted:", {
      firstName: "John",
      lastName: "Doe",
      email: "john_doe@example.com",
      message: "This is a test message."
    });
  });
})

Cypress-Test ausführen

Beispielausgabe:

  (Ergebnisse)

  ┌────────────────────────────────────────────────────────────────────────────────────────────────┐
  │ Tests:        1                                                                                │
  │ Erfolgreich:  1                                                                                │
  │ Fehlgeschl.:  0                                                                                │
  │ Ausstehend:   0                                                                                │
  │ Übersprungen: 0                                                                                │
  │ Screenshots:  0                                                                                │
  │ Video:        false                                                                            │
  │ Dauer:        4 Sekunden                                                                       │
  │ Datei:        contact.cy.ts                                                                    │
  └────────────────────────────────────────────────────────────────────────────────────────────────┘


====================================================================================================

  (Testlauf beendet)


       Testdatei                                         Tests  Erfolgreich  Fehlgeschl.  Offen  Skip  
  ┌────────────────────────────────────────────────────────────────────────────────────────────────┐
  │ ✔  contact.cy.ts                            00:04        1        1        -        -        - │
  └────────────────────────────────────────────────────────────────────────────────────────────────┘
    ✔  Alle Tests bestanden!                    00:04        1        1        -        -        -  

Falls eine Fehlermeldung wie „Cypress failed to verify that your server is running“ erscheint, starte den Server neu mit:

Führe den Cypress-Test anschließend erneut aus.

GitHub Actions für Cypress CI/CD einrichten

Nach erfolgreichem lokalem Testen von Cypress kannst du GitHub Actions so konfigurieren, dass alle Tests automatisch bei jedem Push ausgeführt werden. So wird sichergestellt, dass dein Code laufend geprüft wird.

Workflow-Datei erstellen

Erzeuge eine neue Datei im Verzeichnis für GitHub-Workflows:

$ mkdir -p .github/workflows
$ nano .github/workflows/cypress-e2e.yml

Workflow-Konfiguration einfügen

Füge folgenden Inhalt ein, um bei jedem Push automatische Cypress-Tests auszuführen:

name: Cypress E2E Tests

on:
  push:
    branches:
      - main
  pull_request:

jobs:
  cypress-run:
    runs-on: ubuntu-latest

    services:
      web:
        image: node:18
        ports:
          - 3000:3000
        options: >-
          --health-cmd "curl --fail http://localhost:3000 || exit 1"
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

    steps:
      - name: Repository auschecken
        uses: actions/checkout@v4

      - name: Node.js einrichten
        uses: actions/setup-node@v4
        with:
          node-version: '18'

      - name: Abhängigkeiten installieren
        run: npm install

      - name: Anwendung starten
        run: npm run dev &
        env:
          PORT: 3000

      - name: Auf Server warten
        run: npx wait-on http://localhost:3000

      - name: Cypress Tests ausführen
        run: npx cypress run

Diese Konfiguration führt folgende Schritte aus:

  • Reagiert auf Pushes und Pull Requests auf den Branch main.
  • Installiert Node.js und Abhängigkeiten.
  • Startet den Server und wartet auf Erreichbarkeit.
  • Führt alle Cypress-End-to-End-Tests aus.

Workflow committen und hochladen

Speichere die Datei, committe deine Änderungen und pushe den Workflow ins Repository:

$ git add .
$ git commit -m "Add GitHub Actions workflow for Cypress E2E tests"
$ git push origin main

Workflow-Verlauf prüfen

Wechsle im GitHub-Repository zur Registerkarte Actions, um den Workflow zu beobachten. Nach dem Ausführen zeigt der Job die Ergebnisse deiner Cypress-Tests an.

Bei Problemen helfen dir die bereitgestellten Protokolle zur Fehlersuche weiter.

Fehlgeschlagene Cypress-Tests automatisch speichern

Cypress speichert automatisch Screenshots von fehlerhaften Tests, um das Debugging zu erleichtern. Mit GitHub Actions kannst du diese Bilder als Artefakte speichern. So aktivierst du die Screenshot-Funktion:

Screenshots aktivieren

Bearbeite die Konfigurationsdatei von Cypress:

Füge unterhalb der baseUrl-Zeile Folgendes hinzu:

screenshotOnRunFailure: true,  // Screenshots aktivieren  
screenshotsFolder: "cypress/screenshots",  // Speicherort festlegen

Beispielkonfiguration mit Screenshot-Option

import { defineConfig } from "cypress";

export default defineConfig({
  e2e: {
    baseUrl: process.env.BASE_URL || 'http://localhost:3000',
    screenshotOnRunFailure: true,  // Screenshots aktivieren  
    screenshotsFolder: "cypress/screenshots",  // Speicherort festlegen
    setupNodeEvents(on, config) {
      // implement node event listeners here
    },
  },
});

Fehlgeschlagenen Test simulieren

Sichere die bestehende Testdatei:

$ cp cypress/e2e/contact.cy.ts cypress/e2e/contact.cy.ts.ORIG

Bearbeite die Testdatei, um absichtlich einen Fehler zu erzeugen:

Ändere die E-Mail-Adresse im Test wie folgt:

...
cy.get('input[name="email"]').type('john@example.com');
...

Test ausführen und Fehlerausgabe prüfen

Die Ausgabe bestätigt, dass der Test fehlgeschlagen ist und ein Screenshot gespeichert wurde:

(Screenshots)

-  /home/linuxuser/my-project/cypress/screenshots/contact.cy.ts/Contact Page Tests -- Sub     
   mits the form successfully (failed).png                                                        

====================================================================================================

(Run Finished)

     Spec                                              Tests  Passing  Failing  Pending  Skipped  
┌────────────────────────────────────────────────────────────────────────────────────────────────┐
│ ✖  contact.cy.ts                            00:06        1        -        1        -        - │
└────────────────────────────────────────────────────────────────────────────────────────────────┘
  ✖  1 of 1 failed (100%)                     00:06        1        -        1        -        -  

Wechsle in den Ordner cypress/screenshots/contact.cy.ts/ und öffne den Screenshot mit dem Namen:

  • Contact Page Tests -- Submits the form successfully (failed).png

CI/CD-Pipeline mit GitHub Actions konfigurieren

Workflows in GitHub bestehen aus Jobs und Steps, die CI/CD-Prozesse automatisieren. Ein Job definiert eine Abfolge von Anweisungen, während Schritte konkrete Befehle darstellen. So richtest du eine neue Workflow-Datei ein:

Workflow-Datei erstellen

$ mkdir -p .github/workflows
$ nano .github/workflows/cypress.yml

CI/CD-Workflow-Konfiguration einfügen

name: CI/CD Pipeline
on: 
 push:
  branches:
      - main

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - name: Repository auschecken
        uses: actions/checkout@v4

      - name: Node.js einrichten
        uses: actions/setup-node@v4
        with:
          node-version: 18.x

      - name: Abhängigkeiten installieren
        run: npm install

      - name: Next.js-Anwendung bauen
        run: npm run build

      - name: Cypress Tests ausführen
        uses: cypress-io/github-action@v6
        with:
          start: npm start
          browser: chrome

      - name: Screenshots hochladen
        if: failure()
        uses: actions/upload-artifact@v4
        with:
          path: cypress/screenshots

Diese Pipeline beinhaltet folgende Schritte:

  • Repository auschecken: Holt den Code mit actions/checkout@v4.
  • Node.js einrichten: Installiert Node.js Version 18.
  • Installieren & Bauen: Installiert Abhängigkeiten und baut die Next.js-Anwendung.
  • Cypress-Testausführung: Führt E2E-Tests im Chrome-Browser aus.
  • Artefakte hochladen: Speichert automatisch Screenshots fehlgeschlagener Tests.

Code ins GitHub-Repository hochladen

Initialisiere das Git-Repository und lade deine Änderungen hoch:

$ git init
$ git add .
$ git commit -m "Cypress E2E test workflow"
$ git remote add origin https://github.com/example-user/cypress-dev-test
$ git push -u origin main

GitHub Actions-Protokolle überprüfen

GitHub stellt umfangreiche Protokolle bereit, um alle Schritte im Workflow zu überwachen. So kannst du sie einsehen:

  • Öffne den Tab Actions in deinem Repository.
  • Klicke auf den letzten Workflow-Lauf, um eine Zusammenfassung zu erhalten.
  • Sieh dir die Testergebnisse im Cypress-Bereich an.
  • Rufe gespeicherte Screenshots über Artifacts ab.

Jobausführung analysieren

Klicke im linken Bereich auf den Test-Job, um alle Einzelschritte einzusehen. Du erhältst Informationen zu:

  • Befehlen: Alle ausgeführten Shell-Befehle.
  • Ausgaben: Terminalantworten und Testergebnisse.
  • Zeitstempel: Laufzeit jedes einzelnen Schrittes.

Slack-Benachrichtigungen bei Cypress-Fehlschlägen aktivieren

Mit Slack-Integration erhält dein Team sofortige Hinweise auf fehlgeschlagene Cypress-Tests in GitHub Actions. So richtest du die Benachrichtigungen ein:

Slack Webhook konfigurieren

  • Installiere die App Incoming Webhooks in deinem Slack-Workspace.
  • Wähle einen Kanal für die Meldungen (z. B. #ci-cd-alerts) oder erstelle einen neuen.
  • Schließe die Einrichtung ab und kopiere die generierte Webhook-URL.

Webhook in GitHub Secrets speichern

  1. Öffne die Settings deines GitHub-Repos.
  2. Gehe zu Secrets and Variables > Actions.
  3. Klicke auf New Repository Secret.
  4. Setze den Namen auf SLACK_WEBHOOK_URL.
  5. Füge die kopierte Webhook-URL als Secret-Wert ein.

CI/CD-Workflow bearbeiten

Öffne deine Workflow-Datei zur Bearbeitung:

$ nano .github/workflows/cypress.yml

Slack-Benachrichtigung hinzufügen

Füge am Ende der Datei folgenden Schritt hinzu:

- name: Notify Slack
  if: failure()
  uses: rtCamp/action-slack-notify@v2
  env:
    SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
    SLACK_COLOR: ${{ job.status }}

Diese Konfiguration verwendet das gespeicherte Secret SLACK_WEBHOOK_URL, um bei Fehlschlägen eine Nachricht an den definierten Slack-Kanal zu senden.

Nach Aktivierung dieser Integration sendet GitHub Actions bei jedem Fehler automatisch eine Slack-Benachrichtigung mit Link zum Protokoll.

Fazit

Du hast erfolgreich eine CI/CD-Pipeline mit GitHub Actions und Cypress für eine Beispielanwendung mit Next.js eingerichtet. Die Pipeline führt automatisierte Tests bei jedem Push auf den main-Branch aus, speichert Screenshots fehlgeschlagener Tests und benachrichtigt dich per Slack bei Problemen.

Mit dieser Automatisierung wird dein Entwicklungsprozess effizienter, zuverlässiger und reaktionsschneller. Für fortgeschrittene Setups wie Kubernetes-Deployments siehe die Anleitung zur CI/CD-Integration mit GitHub Actions und Kubernetes Engine.

Quelle: vultr.com

Jetzt 200€ Guthaben sichern

Registrieren Sie sich jetzt in unserer ccloud³ und erhalten Sie 200€ Startguthaben für Ihr Projekt.

Das könnte Sie auch interessieren:

Moderne Hosting Services mit Cloud Server, Managed Server und skalierbarem Cloud Hosting für professionelle IT-Infrastrukturen

PHP-App mit Docker, Nginx und MySQL deployen

Linux Basics, Tutorial
Kompletten PHP-Stack mit Docker und Docker-Compose bereitstellen Ein typisches PHP-Setup besteht aus drei Hauptkomponenten: einem Webserver, einem relationalen Datenbanksystem und dem PHP-Interpreter. In dieser Anleitung setzen wir eine vollständige PHP-Umgebung…