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
$ sudo apt update
Node.js und NPM installieren
$ sudo apt install nodejs npm -y
Node.js-Version prüfen
$ node -v
Die Ausgabe sollte Version 18.x oder höher anzeigen:
v18.19.1
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
$ cd
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
$ cd my-project
Verzeichnisstruktur anzeigen
$ ls
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
$ sudo ufw allow 3000
Falls UFW nicht installiert ist, verwende diesen Befehl:
$ sudo apt install ufw -y && sudo ufw allow ssh
UFW-Konfiguration neu laden
$ sudo ufw reload
Entwicklungsserver starten
$ npm run dev
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
$ pwd
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
$ nano app/page.tsx
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:
$ npm run dev &
Ö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
$ npx cypress open
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
$ ls
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:
$ nano cypress.config.ts
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
$ npx cypress run
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:
$ npm run dev
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:
$ nano cypress.config.ts
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:
$ nano contact.cy.ts
Ä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
$ npx cypress run
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
- Öffne die Settings deines GitHub-Repos.
- Gehe zu Secrets and Variables > Actions.
- Klicke auf New Repository Secret.
- Setze den Namen auf
SLACK_WEBHOOK_URL
. - 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.