NCA Social Media
Aktualisiert:
Autor:
Roland Golla
Grüne Werkzeugkiste mit geteilten Werkzeugen für Teams, Custom Commands

Was sind Cypress Custom Commands?

Cypress Custom Commands sind eigene Befehle, die du mit Cypress.Commands.add registrierst und danach wie cy.get oder cy.visit in jedem Test aufrufst. Sie bündeln wiederkehrende Abläufe wie Login, Selektoren oder Setup Schritte an einer Stelle.

Du legst sie meist in cypress/support/commands.js oder commands.ts ab. Die Support Datei lädt vor jedem Spec, deshalb stehen die Commands überall bereit. Mit Cypress.Commands.overwrite änderst du außerdem das Verhalten eingebauter Befehle, etwa um Passwörter im Log zu verbergen.

Gut gebaut sind Custom Commands mehr als eine Abkürzung. Sie sind die gemeinsame Sprache deiner Suite. Wer cy.login liest, weiß sofort, was passiert. Und wer einen neuen Test schreibt, ob Mensch oder KI Agent, nutzt dieselben geprüften Bausteine statt jedes Mal neu zu erfinden, wie man sich anmeldet.

Cypress Custom Commands mit NCA: Schnelle Hilfe vom Experten

Cypress mit Cypress Cloud nutzen wir täglich in Production. Roland Golla ist offizieller Cypress Ambassador, arbeitet seit über zwanzig Jahren an Testing und Refactoring und baut bei NCA seit 2013 automatisierte Tests. Custom Commands schreiben wir nicht nur für Projekte, wir pflegen sie auch als Open Source: Das NCA TESTIFY Cypress Plugin ist eine Sammlung genau solcher Commands, unter MIT Lizenz.

Passend dazu: der Cypress Workshop mit Roland Golla, die Cypress Remote Schulung für Teams, die Vibe Coding Beratung für Teams mit KI Agenten, unser Leitfaden zu rules.md und AGENTS.md und der Artikel zu Quality Gates für KI Code.

NCA Cypress Workshop mit Cypress Ambassador Roland Golla

E2E Tests, die euer Team selbst schreibt

Ein Tag inhouse mit Roland Golla, offizieller Cypress Ambassador und seit über 20 Jahren in Testing und Refactoring zu Hause. Auf unserem YouTube Kanal zeigt er in über 70 Live Coding Tutorials, wie Cypress in echten Projekten läuft. Dazu kommt unser Open Source Plugin NCA TESTIFY: Basistests für jede Website, mit einer Zeile im CI/CD Setup. Im Workshop lernt euer Team Setup, stabile Selektoren, Custom Commands und Tests in der Pipeline.

  1. 1
    Kostenloses Vorgespräch
    Projekt, Stack und Teststand klären
  2. 2
    Workshoptag bei euch
    Setup, Patterns und erste Tests im Team
  3. 3
    Praxistag optional
    Tests im eigenen Projekt und in CI
Roland Golla
Roland Golla
Fullstack Developer
Zum Cypress Workshop arrow_forward

Cypress.Commands.add: der erste eigene Command

Ein Command braucht einen Namen und eine Funktion. Das klassische erste Beispiel ist ein Helper für data-cy Attribute. Diese Attribute setzt du nur für Tests. Sie ändern sich nicht, wenn jemand CSS Klassen umbaut oder Texte übersetzt.

Code:
          

// cypress/support/commands.js
Cypress.Commands.add('dataCy', (value) => {
  return cy.get(`[data-cy=${value}]`)
})

Im Test liest sich das danach so:

Code:
          

it('legt einen Artikel in den Warenkorb', () => {
  cy.visit('/produkte')
  cy.dataCy('add-to-cart').first().click()
  cy.dataCy('cart-count').should('have.text', '1')
})

Über die Option prevSubject legst du fest, wie sich ein Command in eine Kette einfügt:

  • false ist der Standard. Der Command startet eine neue Kette, wie cy.dataCy.
  • true macht einen Child Command. Er braucht ein vorheriges Subject, etwa ein Element aus cy.get.
  • optional macht einen Dual Command, der mit und ohne Subject funktioniert.

Zusätzlich kannst du das Subject auf element, document oder window einschränken. Cypress prüft das dann für dich.

TypeScript Typen: declare global namespace Cypress

In TypeScript kennt der Compiler deinen Command erst, wenn du ihn deklarierst. Dafür erweiterst du das Interface Chainable im globalen Namespace Cypress. Danach bekommst du Autovervollständigung in VS Code oder PhpStorm, und Tippfehler fallen schon vor dem Testlauf auf.

Code:
          

// cypress/support/commands.ts
Cypress.Commands.add('dataCy', (value: string) => {
  return cy.get(`[data-cy=${value}]`)
})

declare global {
  namespace Cypress {
    interface Chainable {
      /**
       * Holt ein Element über sein data-cy Attribut.
       * @example cy.dataCy('add-to-cart')
       */
      dataCy(value: string): Chainable<JQuery<HTMLElement>>
      login(email: string, password: string): Chainable<void>
    }
  }
}

export {}

Zwei Details sparen dir Ärger:

  • export {} am Ende: declare global funktioniert nur in einem Modul. Hat deine Datei keinen import und keinen export, macht diese Zeile sie zu einem.
  • types in der tsconfig: In cypress/tsconfig.json setzt du types auf cypress und node. So kollidieren die Cypress Typen nicht mit anderen globalen Typen, etwa aus @types/chai oder @types/jquery.
Code:
          

{
  "compilerOptions": {
    "types": ["cypress", "node"]
  }
}

Der JSDoc Kommentar ist kein Beiwerk. Er erscheint beim Hovern in der IDE und dient Menschen wie KI Agenten als Kurzdoku direkt am Command.

Login mit cy.session: der wichtigste Command

Fast jede Suite braucht einen Login. Ohne Command steht er in jedem Spec, mit kleinen Abweichungen. Mit cy.session im Command läuft der Login einmal, danach stellt Cypress Cookies, Local Storage und Session Storage aus dem Cache wieder her. Seit Cypress 12 ist cy.session ohne Experiment Flag verfügbar.

Code:
          

Cypress.Commands.add('login', (email, password) => {
  cy.session(
    [email, password],
    () => {
      cy.visit('/login')
      cy.dataCy('login-email').type(email)
      cy.dataCy('login-password').type(password, { log: false })
      cy.dataCy('login-submit').click()
      cy.url().should('include', '/dashboard')
    },
    {
      validate() {
        cy.request('/api/me').its('status').should('eq', 200)
      },
      cacheAcrossSpecs: true
    }
  )
})

Was hier passiert:

  • Die ID aus Mail und Passwort trennt die Sessions verschiedener Nutzer sauber.
  • validate prüft eine wiederhergestellte Session. Schlägt die Prüfung fehl, läuft der Login neu.
  • cacheAcrossSpecs teilt die Session über mehrere Specs im selben Lauf auf derselben Maschine.
  • log: false hält das Passwort aus dem Command Log heraus.
Code:
          

beforeEach(() => {
  // Fake Nutzer aus dem lokalen Seed
  cy.login('redaktion@example.test', 'lokales-testpasswort')
  cy.visit('/dashboard')
})

Hat deine App einen API Login, geht es noch schneller. Die Cypress Doku rät, die Oberfläche beim Setup so oft wie möglich zu überspringen, etwa mit cy.request. Den Login über das Formular testest du dann genau einmal, in einem eigenen Spec.

Eingebaute Befehle mit overwrite erweitern

Mit Cypress.Commands.overwrite greifst du in einen bestehenden Befehl ein. Du bekommst die Originalfunktion als ersten Parameter und entscheidest, was davor oder danach passiert. Das Beispiel aus der Cypress Doku maskiert sensible Eingaben im Log:

Code:
          

Cypress.Commands.overwrite('type', (originalFn, element, text, options) => {
  if (options && options.sensitive) {
    options.log = false
    Cypress.log({
      $el: element,
      name: 'type',
      message: '*'.repeat(text.length)
    })
  }

  return originalFn(element, text, options)
})

Code:
          

cy.dataCy('login-password').type('lokales-testpasswort', { sensitive: true })

Overwrite ist mächtig und deshalb gefährlich. Wer cy.visit oder cy.click verbiegt, ändert das Verhalten jedes Tests, oft ohne dass es jemand merkt. Unsere Regel: Overwrite nur für Querschnittsthemen wie Logging oder Umgebungen, immer mit Kommentar und immer im Review besprochen.

Custom Command, Page Object oder normale Funktion?

Nicht jede Wiederholung gehört in einen Command. Die Cypress Doku ist da deutlich: Mach nicht alles zu einem Custom Command. Commands sind für Verhalten gedacht, das du in sehr vielen Tests brauchst. Logik für einen einzelnen Spec bleibt eine normale Funktion.

Page Objects sind die dritte Option. Sie kapseln Selektoren und Abläufe einer Seite in einer Klasse. Das NCA TESTIFY Plugin bringt dafür zum Beispiel eine BasePage Klasse mit. Bei Cypress lohnt sich trotzdem ein kritischer Blick, denn Page Objects zwingen Tests oft durch die Oberfläche, auch wenn ein direkter Weg über cy.request schneller wäre.

Unsere Faustregel in drei Fragen:

  • Brauchen es viele Specs? Dann Custom Command.
  • Gehört es zu genau einer Seite mit vielen Elementen? Dann Page Object oder ein Modul mit Funktionen.
  • Braucht es nur dieser eine Spec? Dann normale Funktion im Spec oder in einer Helper Datei.

Custom Command, Page Object und Funktion im Vergleich

Custom Command Page Object Normale Funktion
Aufruf: cy.login() in der Cypress Kette Aufruf: loginPage.submit() über eine Klasse Aufruf: fillAddress() direkt im Spec
Gut für: Abläufe, die viele Specs teilen Gut für: Seiten mit vielen Elementen und Zuständen Gut für: Logik für einen oder wenige Specs
Stärke: global in jedem Spec verfügbar, lesbar wie ein eingebauter Befehl Stärke: Selektoren einer Seite an einem Ort Stärke: kein globaler Zustand, leicht zu lesen
Risiko: zu viele kleine Commands verstecken, was passiert Risiko: zusätzlicher Zustand, Tests laufen immer durch die UI Risiko: Kopien verteilen sich, wenn niemand aufräumt
TypeScript: Chainable Interface erweitern TypeScript: normale Klasse mit Typen TypeScript: normale Funktionssignatur
Für KI Agenten: in AGENTS.md als feste Bausteine nennen Für KI Agenten: Klassenstruktur erklären Für KI Agenten: meist ohne extra Kontext verständlich

Commands als geteilte Patterns: Qualität gehört dem Team

Custom Commands entfalten ihren Wert erst, wenn das ganze Team sie nutzt. Dann wird aus einer Sammlung von Helfern ein gemeinsames Vokabular. Ein Frontend Entwickler schreibt seinen ersten E2E Test mit cy.login und cy.dataCy und muss nicht wissen, wie der Login intern funktioniert. So übernehmen Teams Qualität selbst, statt sie an eine einzelne Testperson abzugeben.

Damit das trägt, halten wir uns an die Best Practices der Cypress Doku und ein paar eigene Regeln:

  • Nicht übertreiben: Kein cy.clickButton, das nur click aufruft. Lesbarkeit schlägt DRY.
  • Nicht zu viel in einen Command: Commands bleiben kombinierbar. Assertions entscheidet der aufrufende Test.
  • UI beim Setup überspringen: Login, Testdaten und Zustände lieber per cy.request, Cookies oder Local Storage herstellen.
  • Typen und JSDoc für jeden Command: Wer ihn nutzt, sieht sofort Parameter und Zweck.
  • Ein Ort, ein Owner: Commands liegen in cypress/support und ändern sich nur per Review.

Wird die Sammlung größer, lohnt ein eigenes Paket. Genau so ist das NCA TESTIFY Cypress Plugin entstanden: Commands mit dem Präfix tt wie ttEveryInternalLinkStatusOk oder ttAccessibility, die über npm in jedes Projekt kommen. Ein Import in der Support Datei, und alle Commands sind registriert.

Code:
          

npm install cypress-ncatestify-plugin --save-dev

Code:
          

// cypress/support/e2e.ts
import 'cypress-ncatestify-plugin'

Custom Commands als Kontext für KI Agenten

Ein KI Agent, der Cypress Tests schreibt, erfindet ohne Kontext gern seinen eigenen Login, eigene Selektoren und eigene Wartezeiten. Das Ergebnis läuft vielleicht, passt aber nicht zur Suite. Custom Commands lösen das, wenn der Agent sie kennt. Der einfachste Weg führt über deine AGENTS.md.

Code:
          

## Cypress Tests

- Selektoren nur über cy.dataCy('name'), nie über CSS Klassen oder Texte.
- Login immer mit cy.login(email, password). Nie das Formular im Test ausfüllen.
- Keine festen Wartezeiten mit cy.wait(Zahl).
- Neue Custom Commands nur nach Rücksprache. Bestehende Commands nicht ändern.
- Bestehende Specs nicht abschwächen oder löschen. Neue Tests als eigene Datei.
- Testdaten nur aus dem lokalen Faker Seed.

Dazu kommen die TypeScript Typen. Agenten lesen commands.ts und die JSDoc Kommentare und verstehen so Parameter und Zweck jedes Commands. Gute Typen sind damit doppelt wertvoll: für die IDE und für den Agenten.

Der Ablauf bleibt bei NCA immer gleich:

  • Der Agent schreibt Tests mit den vorhandenen Commands, gegen eine lokale Umgebung mit Fake Daten.
  • Quality Gates in CI laufen zuerst: statische Analyse, Unit Tests, funktionale Tests, Cypress E2E.
  • Ein Mensch reviewt und gibt frei. Testdateien und Commands sind geschützt.

Wie Agenten Tests gegen Anforderungen schreiben, zeigt unser Artikel zu agentischen Akzeptanztests. Wie der Agent danach Testergebnisse aus der Cloud liest, steht bei Cypress Cloud MCP. Und wie OpenCode als Coding Agent arbeitet, erklärt unsere Seite zu OpenCode Features und Plugins.

Ein Hinweis für Teams mit Cypress UI Coverage: Eigene Commands zählen dort erst als Interaktion, wenn du sie in der Konfiguration unter additionalInteractionCommands einträgst.

After adding a custom command, the tests can use it just like any built-in command.

Gleb Bahmutov, Cypress.io – Cypress Blog

Aus der NCA Praxis: wenige Commands, klare Regeln

Die beste Command Sammlung ist klein. Wir beraten Teams oft dabei, Commands eher zu streichen als neue zu bauen. Übrig bleiben Login, Selektor Helper, Setup über die API und ein paar fachliche Abläufe, die wirklich überall vorkommen. Alles andere wird wieder zur normalen Funktion. Das macht die Suite lesbarer, für neue Leute im Team genauso wie für KI Agenten.

Bei KI gestützter Entwicklung sind Commands für uns ein Teil der Guardrails für Agentic AI Coding. Sie legen fest, wie getestet wird, so wie ein Schema festlegt, wie Daten aussehen. Mehr dazu findest du in unserem Artikel zu Schema Based AI Coding.

Weiterlesen: wie wir Code Qualität mit KI Agenten sichern, warum Tests für uns lebende Spezifikation sind und wie die KI Weiterbildung für Entwicklerteams Teams beim gemeinsamen Arbeiten mit Agenten unterstützt.

Passend dazu im NCA Cypress Glossar: Testdaten in Cypress für Setup über API und Seeding, Cypress UI Coverage, wo eigene Commands erst nach Konfiguration zählen, und Self Healing Tests als Gegenentwurf zu zentral gepflegten Selektoren.

CYPRESS.IO Ambassador und IT Consultant für QA Engenieering und Qualität in PHP Projekten.

Frontend 2025: Optimieren Sie Ihre Webseite mit Astro JS und nutzen Sie die Vorteile der Barrierefreiheit

Optimieren Sie Ihre Webseite mit Astro JS und nutzen Sie die Vorteile einer schnellen, sicheren und barrierefreien Webseite. Erfüllen Sie die gesetzlichen Anforderungen und verbessern Sie die Benutzererfahrung Ihrer Webseite. Mit Astro JS können Sie die Ladezeit reduzieren, die Sicherheit maximieren und die SEO-Optimierung verbessern. Kontaktieren Sie uns, um mehr zu erfahren und um Ihre Webseite auf ein neues Level zu heben.

Astro JS Frontend E-Mail Kontakt

Häufige Fragen zu Cypress Custom Commands

Die wichtigsten Antworten zu Custom Commands in Cypress: Syntax, TypeScript, Login mit cy.session, overwrite, Page Objects und KI Agenten.

Was sind Cypress Custom Commands 2026?

Custom Commands sind eigene Befehle, die du mit Cypress.Commands.add registrierst und danach wie cy.get in jedem Test nutzt. Sie bündeln wiederkehrende Abläufe wie Login, Selektoren oder Setup an einer Stelle. Meist liegen sie in cypress/support/commands.js oder commands.ts. Die Support Datei lädt vor jedem Spec, deshalb sind sie überall verfügbar.

Wie typisiere ich Custom Commands 2026 in TypeScript?

Du erweiterst das Interface Chainable im globalen Namespace Cypress, also mit declare global und namespace Cypress. Dort trägst du jede Signatur ein, etwa dataCy mit Rückgabe Chainable von JQuery. Hat die Datei keinen import oder export, ergänze export {} am Ende. In cypress/tsconfig.json setzt du types auf cypress und node.

Wie baue ich 2026 einen Login Command mit cy.session?

Du registrierst einen Command login und rufst darin cy.session mit einer ID, einer Setup Funktion und Optionen auf. Die Setup Funktion meldet sich an, validate prüft eine wiederhergestellte Session. Mit cacheAcrossSpecs teilst du die Session über mehrere Specs im selben Lauf. Seit Cypress 12 brauchst du dafür kein Experiment Flag mehr.

Wann nutze ich 2026 Custom Commands statt Page Objects?

Custom Commands passen für Abläufe, die viele Specs teilen, etwa Login oder Selektor Helper. Page Objects passen für einzelne Seiten mit vielen Elementen und Zuständen. Die Cypress Doku warnt davor, alles zu einem Command zu machen. Logik, die nur ein Spec braucht, bleibt eine normale Funktion. Beides lässt sich sinnvoll kombinieren.

Helfen Custom Commands 2026 KI Agenten beim Testen?

Ja, wenn der Agent sie kennt. Nenn die wichtigsten Commands in deiner AGENTS.md und schreib klare Regeln dazu, etwa nur cy.dataCy für Selektoren und cy.login für die Anmeldung. Typen und JSDoc Kommentare liefern zusätzlichen Kontext. Der Agent schreibt die Tests, ein Mensch reviewt und gibt frei. Bestehende Commands bleiben geschützt.

Was ist der Unterschied zwischen add und overwrite?

Mit Cypress.Commands.add legst du einen neuen Befehl an. Mit Cypress.Commands.overwrite änderst du einen vorhandenen, etwa type oder visit. Overwrite bekommt die Originalfunktion als ersten Parameter, damit du das alte Verhalten aufrufen kannst. Weil overwrite jeden Test betrifft, gehört jede Änderung kommentiert und im Review besprochen.

Was bedeutet prevSubject?

Die Option prevSubject legt fest, wie sich ein Command in eine Kette einfügt. Mit false, dem Standard, startet er eine neue Kette. Mit true ist er ein Child Command und braucht ein vorheriges Subject. Mit optional funktioniert er mit und ohne Subject. Zusätzlich kannst du das Subject auf element, document oder window einschränken.

Warum data-cy Attribute statt CSS Klassen?

Weil data-cy Attribute nur für Tests da sind. CSS Klassen ändern sich beim Redesign, Texte bei Übersetzungen, IDs manchmal durch Frameworks. Ein data-cy Attribut bleibt stabil, solange die Funktion gleich bleibt. Ein kleiner Command wie cy.dataCy macht die Nutzung bequem und sorgt dafür, dass alle im Team dieselbe Schreibweise nutzen.

Wie verberge ich Passwörter im Command Log?

Am einfachsten mit der Option log false bei type, so wie im Login Command. Für eine einheitliche Lösung zeigt die Cypress Doku ein overwrite Beispiel für type mit einer Option sensitive. Dann schreibt Cypress statt des Passworts nur Sternchen ins Log. Nutze in Tests trotzdem nur Fake Zugangsdaten aus deinem lokalen Seed.

Wie viele Custom Commands sind sinnvoll?

So wenige wie möglich. Die Cypress Doku rät von Commands ab, die nur einen einzelnen Befehl umhüllen, etwa cy.clickButton. Lesbarkeit geht vor DRY. Eine kleine Sammlung aus Login, Selektor Helper, Setup über die API und wenigen fachlichen Abläufen trägt in den meisten Projekten weit. Alles andere bleibt normale Funktion.

Kann ich Custom Commands als npm Paket teilen?

Ja. Du packst die Commands in ein eigenes Paket und importierst es in der Support Datei. Damit registrieren sich alle Commands automatisch. So funktioniert zum Beispiel das NCA TESTIFY Cypress Plugin, ein Open Source Paket mit Commands wie ttAccessibility. Denk an die TypeScript Deklarationen, damit Nutzer Autovervollständigung bekommen.

Zählen Custom Commands in Cypress UI Coverage?

Nicht automatisch. UI Coverage wertet standardmäßig nur eingebaute Interaktionsbefehle wie click, type oder check aus. Eigene Commands trägst du in Cypress Cloud im Tab App Quality unter additionalInteractionCommands ein, mit dem Namen ohne das Präfix cy. Nimm dort nur Commands auf, die wirklich mit einem Element arbeiten.