Cypress Setup und Grundlagen für Magento-Frontends
PASS
expect()
Testing · Cypress · E2E-Testing · Magento 2
Cypress Setup und Grundlagen für Magento-Frontends
Der Einstieg in stabile E2E-Tests für Hyvä-Shops

Wer Magento- und Hyvä-Shops ohne verlässliche End-to-End-Tests betreibt, verlässt sich beim Checkout, bei der Produktsuche und bei jedem Deployment auf reines Glück statt auf belastbare Sicherheit. Dieser Artikel zeigt die Cypress-Grundlagen für Magento-Frontends von Grund auf: Installation, Konfiguration von baseUrl und Umgebungsvariablen für dev, staging und production, eine saubere Projektstruktur sowie den ersten lauffähigen Test gegen eine echte Seite.

12 Min. Lesezeit Cypress · npm · cypress.config.js Magento 2.4.8 · Hyvä Theme · CI/CD

1. Warum End-to-End-Tests mit Cypress für Magento-Frontends unverzichtbar sind

Magento-Frontends mit Hyvä Theme und Alpine.js sehen auf den ersten Blick einfach aus, verstecken aber komplexe Interaktionsketten: Warenkorb-Updates per AJAX, Mini-Cart-Zustände, Konfigurationsprodukte mit dynamischer Preisberechnung und mehrstufige Checkout-Flows. PHPUnit-Tests prüfen zuverlässig einzelne Klassen und Services, sagen aber nichts darüber aus, ob ein Kunde im echten Browser tatsächlich einen Artikel in den Warenkorb legen und bis zur Bestellbestätigung durchklicken kann. Genau diese Lücke schließt End-to-End-Testing mit einem echten Browser-Rendering.

Cypress unterscheidet sich von klassischen Selenium-Setups durch automatisches Warten auf DOM-Änderungen, eingebautes Time-Travel-Debugging mit Snapshots jedes Testschritts und eine Architektur, die direkt im selben Prozess wie der Browser läuft, statt über einen externen WebDriver zu kommunizieren. Für Magento-Teams bedeutet das spürbar weniger flackernde Tests und deutlich schnellere Feedback-Zyklen bei jedem Deployment, gerade wenn Checkout oder Produktsuche nach einem Release regelmäßig manuell nachgeprüft werden mussten.

2. Cypress installieren: npm, Node-Version und Projekt-Setup

Cypress wird als reguläre devDependency über npm oder yarn installiert und bringt seinen eigenen Electron-Browser sowie Unterstützung für Chrome, Firefox und Edge mit. Eine aktuelle Node-Version (mindestens Node 18) reicht als Voraussetzung, eine PHP- oder Magento-spezifische Toolchain wird nicht benötigt. Nach der Installation erzeugt der erste Aufruf von npx cypress open automatisch die Standard-Ordnerstruktur mit Beispieltests, die sich problemlos löschen lässt, sobald eigene Tests existieren.

In Magento-Projekten empfiehlt sich ein eigenes package.json außerhalb des Composer-Ökosystems, entweder im Projekt-Root oder in einem dedizierten tests/e2e-Verzeichnis, damit Frontend-Tooling und PHP-Abhängigkeiten sauber getrennt bleiben. So lässt sich Cypress unabhängig vom Magento-Build aktualisieren, ohne Composer-Locks zu berühren, und CI-Pipelines können den Testschritt isoliert cachen.


# Install Cypress as a dev dependency for the Magento frontend project
npm install --save-dev cypress

# Alternatively with yarn
yarn add --dev cypress

# Open the interactive Test Runner once to scaffold the cypress/ folder
npx cypress open

# Check the installed Cypress version
npx cypress version

3. cypress.config.js: baseUrl und Umgebungen für dev, staging und production

Die zentrale Konfigurationsdatei cypress.config.js definiert unter anderem baseUrl, specPattern und supportFile. Der wichtigste Punkt für Magento-Projekte: Die baseUrl darf niemals in einzelnen Tests hart kodiert werden, sondern gehört ausschließlich in die Config, damit derselbe Test wahlweise gegen lokale Docker-Umgebung, Staging oder Production laufen kann, ohne eine Zeile Testcode zu ändern.

Für mehrere Umgebungen bieten sich zwei Ansätze an: entweder die Umgebungsvariable CYPRESS_BASE_URL beim Aufruf setzen, oder in setupNodeEvents anhand eines --env environment=staging-Flags eine passende JSON-Datei nachladen. Letzteres eignet sich besonders gut, wenn neben der URL auch Zugangsdaten, Feature-Flags oder API-Endpunkte je Umgebung unterschiedlich sind, ohne dass diese Werte im Repository landen müssen.


const { defineConfig } = require('cypress');

module.exports = defineConfig({
  e2e: {
    // Base URL depends on the environment, override via CYPRESS_BASE_URL
    baseUrl: process.env.CYPRESS_BASE_URL || 'https://magento.local',
    specPattern: 'cypress/e2e/**/*.cy.js',
    supportFile: 'cypress/support/e2e.js',
    viewportWidth: 1280,
    viewportHeight: 800,
    retries: {
      runMode: 2,
      openMode: 0
    },
    setupNodeEvents(on, config) {
      // Load environment specific settings, e.g. staging or production
      const environmentName = config.env.environment || 'dev';
      const environmentConfig = require(`./cypress/config/${environmentName}.json`);
      return { ...config, ...environmentConfig };
    }
  },
  env: {
    environment: 'dev'
  }
});

4. Projektstruktur: e2e/, fixtures/ und support/ sinnvoll organisieren

Cypress schlägt standardmäßig drei zentrale Ordner vor: cypress/e2e für die eigentlichen Testdateien, cypress/fixtures für statische Testdaten wie Beispiel-Produkte oder Kundendaten im JSON-Format, und cypress/support für globale Hooks und wiederverwendbare Commands. In Magento-Projekten hat es sich bewährt, e2e nicht nach Seitentyp, sondern nach fachlicher Domäne zu gliedern, etwa catalog/, checkout/ und customer/, weil Testfälle so näher an den Business-Flows bleiben, die tatsächlich brechen können.

Spec-Dateien sollten konsequent auf *.cy.js enden und pro Datei einen klar abgegrenzten Themenbereich abdecken, statt einen einzigen riesigen Spec mit hunderten Testfällen zu pflegen. Umgebungsspezifische Konfigurationen lassen sich zusätzlich in einem eigenen cypress/config-Ordner ablegen, sodass dev.json, staging.json und production.json sauber voneinander getrennt bleiben und in cypress.config.js gezielt nachgeladen werden können.


cypress/
  e2e/
    catalog/
      product-listing.cy.js
      product-detail.cy.js
    checkout/
      guest-checkout.cy.js
      add-to-cart.cy.js
    customer/
      login.cy.js
      registration.cy.js
  fixtures/
    product.json
    customer.json
  support/
    commands.js
    e2e.js
  config/
    dev.json
    staging.json
    production.json
cypress.config.js
package.json

5. Der erste Test: Startseite und Produktlisting prüfen

Der sinnvollste Einstieg ist ein einfacher Smoke-Test gegen die Startseite: cy.visit('/') lädt die Seite über die konfigurierte baseUrl, anschließend prüfen Assertions, ob die Hauptnavigation sichtbar ist und der Seitentitel den erwarteten Shop-Namen enthält. Dieser erste Test läuft in wenigen Sekunden durch, deckt aber bereits grundlegende Rendering- und Routing-Fehler auf, etwa einen fehlerhaften Full-Page-Cache oder einen kaputten Layout-Handle nach einem Deployment.

Der nächste logische Schritt ist ein Test gegen eine Kategorieseite: Cypress besucht die Produktlisting-Seite und prüft, dass mindestens ein Produkt im Grid gerendert wird und Name sowie Preis pro Produktkachel sichtbar sind. Solche Tests gegen reale Seiten mit echten Daten sind wertvoller als isolierte Component-Tests, weil sie das Zusammenspiel aus Layout-XML, Blöcken und Alpine.js-Interaktionen genau so prüfen, wie es ein Kunde erlebt.


// cypress/e2e/catalog/product-listing.cy.js
describe('Magento homepage and product listing', () => {
  it('loads the homepage and shows the main navigation', () => {
    cy.visit('/');
    cy.get('[data-cy="main-navigation"]').should('be.visible');
    cy.title().should('include', 'Mironsoft');
  });

  it('shows products on the category page', () => {
    cy.visit('/catalog/category/view/id/20');
    cy.get('[data-cy="product-grid-item"]').should('have.length.greaterThan', 0);
    cy.get('[data-cy="product-grid-item"]').first().within(() => {
      cy.get('[data-cy="product-name"]').should('be.visible');
      cy.get('[data-cy="product-price"]').should('be.visible');
    });
  });
});

6. Custom Commands und Support-Dateien für wiederkehrende Magento-Flows

Login, Warenkorb-Interaktionen und das Schließen von Cookie-Bannern tauchen in fast jedem Test auf. Statt diese Schritte in jeder Spec zu wiederholen, gehören sie als Custom Commands in cypress/support/commands.js, registriert über Cypress.Commands.add('login', ...) oder Cypress.Commands.add('addProductToCart', ...). Das reduziert Duplikation drastisch und sorgt dafür, dass sich Änderungen am Login-Flow, etwa nach einem Redesign des Formulars, nur an einer Stelle nachziehen lassen.

Die Datei cypress/support/e2e.js lädt global vor jedem Test und eignet sich für projektweite beforeEach-Hooks, etwa um den Cookie-Consent-Layer standardmäßig zu akzeptieren oder cy.intercept()-Regeln zu registrieren, die für alle Tests gelten sollen. So bleibt jede einzelne Spec-Datei fokussiert auf ihren eigentlichen Testfall, statt sich mit Boilerplate für wiederkehrende Magento-Eigenheiten zu beschäftigen.

7. Headless vs. Headed: cypress run und cypress open im Entwickleralltag

cypress open startet die interaktive Test-Runner-Oberfläche mit sichtbarem Browser, Time-Travel-Debugging und Live-Reload bei jeder Dateiänderung. Dieser Modus ist der richtige Ort, um neue Tests zu schreiben und Selektoren interaktiv zu prüfen, weil jeder Testschritt als Snapshot im DOM inspizierbar bleibt und Netzwerk-Requests direkt im Panel sichtbar sind. Für die tägliche Entwicklung eines neuen Checkout-Tests ist dieser visuelle Modus praktisch unverzichtbar.

cypress run führt dieselben Tests headless und ohne UI aus, deutlich ressourcenschonender und schneller, was ihn zum Standardmodus für CI-Pipelines macht. Mit Flags wie --browser chrome, --spec "cypress/e2e/checkout/**" oder --record lässt sich der Lauf gezielt einschränken oder mit Cypress Cloud verbinden. Screenshots bei Fehlschlägen und optionale Videos jedes Testlaufs werden automatisch unter cypress/screenshots und cypress/videos abgelegt, was das Debuggen fehlgeschlagener CI-Läufe erheblich vereinfacht.

8. Selektoren-Strategie: data-cy-Attribute statt fragiler CSS-Klassen

Ein häufiger Fehler in frühen Cypress-Setups: Tests greifen auf Tailwind-Utility-Klassen wie .flex oder .bg-lime-600 zu, die sich beim nächsten Redesign des Hyvä-Themes ändern, ohne dass sich am fachlichen Verhalten etwas geändert hat. Jede Anpassung am Styling bricht dann stillschweigend Tests, die eigentlich nur prüfen sollten, ob ein Button existiert und klickbar ist. Diese Kopplung zwischen visueller Gestaltung und Testcode ist die häufigste Ursache für brüchige E2E-Suiten.

Die robuste Lösung sind dedizierte data-cy-Attribute direkt in den phtml-Templates, etwa data-cy="add-to-cart-button", die ausschließlich für Tests existieren und von Styling-Änderungen komplett unberührt bleiben. Diese Attribute sollten sparsam und gezielt an Interaktionspunkten wie Buttons, Formularen und Statusanzeigen gesetzt werden, nicht flächendeckend über das gesamte Markup, um das Template lesbar zu halten und den Testfokus auf tatsächlich relevante Elemente zu lenken.

9. CI-Integration: Cypress in GitHub Actions und GitLab CI ausführen

In der CI-Pipeline läuft Cypress praktisch immer headless über cypress run, idealerweise gegen eine frisch deployte Staging-Umgebung statt gegen Produktionsdaten. Die offizielle cypress-io/github-action kümmert sich automatisch um Installation, Node-Modules-Caching und den Testlauf in einem Schritt, während GitLab CI denselben Ablauf über ein Docker-Image mit vorinstalliertem Cypress und einen regulären npm run cypress:run-Job abbildet.

Bei Fehlschlägen sollten Screenshots und Videos als Artefakte hochgeladen werden, damit sich ein fehlgeschlagener CI-Lauf ohne lokale Reproduktion nachvollziehen lässt. Für größere Suiten lohnt sich Parallelisierung über mehrere CI-Jobs mit --record --parallel, um die Gesamtlaufzeit trotz wachsender Testanzahl niedrig zu halten. Die folgende Tabelle fasst die häufigsten Stolperfallen beim Cypress-Setup und die jeweils empfohlene Lösung zusammen.


name: e2e-tests
on:
  pull_request:
  push:
    branches: [main]

jobs:
  cypress-run:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Run Cypress against staging
        uses: cypress-io/github-action@v6
        with:
          browser: chrome
          headless: true
        env:
          CYPRESS_BASE_URL: https://staging.mironsoft-shop.example
          CYPRESS_environment: staging

      - name: Upload screenshots on failure
        if: failure()
        uses: actions/upload-artifact@v4
        with:
          name: cypress-screenshots
          path: cypress/screenshots
Bereich Empfohlener Ansatz Typischer Fehler Warum es zählt
Base-URL baseUrl + CYPRESS_BASE_URL je Umgebung URL hart in jedem Test kodiert Ein Test läuft gegen dev, staging und production
Selektoren data-cy-Attribute in phtml-Templates CSS-Klassen/Tailwind-Utilities als Selektor Tests überleben Redesigns des Hyvä-Themes
Warten cy.intercept() + gezielte Assertions cy.wait(5000) als feste Wartezeit Schnellere, stabilere Tests ohne Ratespiel
Ausführung cypress run --headless in der CI Nur lokal mit cypress open geprüft Regressionen fallen vor dem Deployment auf
Testdaten Fixtures + API-Seeding vor dem Testlauf Tests hängen von manuell angelegten Produkten ab Reproduzierbare Läufe unabhängig vom Datenstand

In der Praxis verstärken sich diese fünf Punkte gegenseitig: Eine saubere baseUrl-Konfiguration bringt wenig, wenn Selektoren bei jedem Styling-Update brechen, und stabile Selektoren nützen wenig, wenn Tests durch feste Wartezeiten trotzdem flackern. Wer alle fünf Empfehlungen konsequent umsetzt, bekommt eine Cypress-Suite, die sich über Monate hinweg zuverlässig warten lässt, statt nach wenigen Wochen ignoriert zu werden.

Mironsoft

E2E-Testing, Cypress-Setup und CI/CD-Integration für Magento-Shops

Cypress-Testing für euren Magento-Shop aufsetzen?

Wir bauen ein stabiles Cypress-Setup für euren Hyvä-Shop auf, von der Projektstruktur über sinnvolle Custom Commands bis zur vollständigen CI-Integration mit aussagekräftigen Fehlerberichten.

Cypress-Setup-Audit

Analyse bestehender Tests, Priorisierung nach Stabilität und Wartbarkeit

Hyvä-Testabdeckung

data-cy-Attribute, Custom Commands und stabile Checkout-Tests

CI/CD-Integration

Headless-Runs in GitHub Actions oder GitLab CI mit Artefakten

10. Zusammenfassung

Ein solides Cypress-Setup für Magento-Frontends beginnt mit einer sauberen Trennung von Testcode und Konfiguration: npm install cypress für die Installation, cypress.config.js mit einer environment-abhängigen baseUrl statt hart kodierter URLs, und eine Projektstruktur, die cypress/e2e, cypress/fixtures und cypress/support klar nach fachlicher Domäne trennt. Der erste Test gegen Startseite und Produktlisting liefert schon nach wenigen Minuten echten Mehrwert, weil er Rendering- und Routing-Fehler aufdeckt, die PHPUnit-Tests grundsätzlich nicht erfassen können.

Der entscheidende Unterschied zwischen einer Cypress-Suite, die über Monate zuverlässig bleibt, und einer, die nach wenigen Wochen ignoriert wird, liegt in den Details: stabile data-cy-Selektoren statt Tailwind-Klassen, cy.intercept() statt fester Wartezeiten, und ein konsequenter Headless-Lauf in der CI-Pipeline statt rein manueller Checks vor jedem Release. Wer diese Grundlagen von Anfang an sauber umsetzt, spart sich monatelange Nacharbeit an einer brüchigen Testsuite.

Cypress Setup für Magento-Frontends - Das Wichtigste auf einen Blick

Installation & Config

npm install --save-dev cypress, baseUrl in cypress.config.js statt hart kodierter URLs.

Projektstruktur

cypress/e2e, cypress/fixtures und cypress/support nach fachlicher Domäne gliedern.

Erster Test & Selektoren

Smoke-Test gegen Startseite/PLP, stabile data-cy-Attribute statt CSS-Klassen.

CI-Integration

cypress run --headless in GitHub Actions/GitLab CI mit Screenshot-Artefakten bei Fehlern.

11. FAQ: Cypress Setup für Magento-Frontends

1Was ist der Unterschied zwischen cypress open und cypress run?
cypress open zeigt die interaktive Oberfläche mit sichtbarem Browser und Time-Travel-Debugging. cypress run läuft headless, schneller und ressourcenschonender, der Standard für CI-Pipelines.
2Wie richte ich unterschiedliche baseUrl-Werte für dev, staging und production ein?
Über CYPRESS_BASE_URL als Umgebungsvariable oder über setupNodeEvents, das anhand eines environment-Flags eine passende JSON-Konfiguration nachlädt.
3Wo sollten Cypress-Tests im Magento-Projekt liegen?
In einem eigenen tests/e2e-Verzeichnis mit eigenem package.json, getrennt vom Composer-Ökosystem, gegliedert nach fachlicher Domäne wie catalog oder checkout.
4Warum sollte ich data-cy-Attribute statt CSS-Klassen als Selektor verwenden?
CSS-/Tailwind-Klassen ändern sich bei Redesigns und brechen Tests stillschweigend. data-cy-Attribute existieren ausschließlich für Tests und bleiben stabil.
5Wie vermeide ich feste Wartezeiten wie cy.wait(5000)?
Mit cy.intercept() gezielt auf Netzwerk-Requests warten statt auf feste Zeiten zu raten. Cypress wartet zudem automatisch auf DOM-Änderungen.
6Kann ich Cypress mit Hyvä/Alpine.js-Komponenten testen?
Ja, Cypress wartet automatisch auf Alpine.js-gesteuerte DOM-Änderungen. Stabile data-cy-Attribute machen solche Interaktionen zuverlässig testbar.
7Wie integriere ich Cypress in GitHub Actions oder GitLab CI?
Über die offizielle cypress-io/github-action in GitHub Actions, oder ein Docker-Image mit vorinstalliertem Cypress und einem npm run cypress:run-Job in GitLab CI.
8Brauche ich für jeden Test eine eigene Fixture-Datei?
Nein, Fixtures nach Datentyp gruppieren, z.B. product.json, und über mehrere Tests wiederverwenden. Für dynamische Daten zusätzlich API-Seeding vor dem Testlauf nutzen.
9Ist Cypress ein Ersatz für PHPUnit-Tests?
Nein, beide ergänzen sich. PHPUnit prüft Klassen isoliert und schnell, Cypress prüft das Zusammenspiel im echten Browser wie ein Kunde es erlebt.
10Sollte Cypress gegen Staging oder gegen Production laufen?
Gegen eine frisch deployte Staging-Umgebung, nicht gegen Produktionsdaten, damit auch destruktive Aktionen gefahrlos getestet werden können.