Selective Testing: Nur betroffene Tests ausführen
PASS
expect()
Testing · CI/CD · Cypress · Playwright
Selective Testing: Nur betroffene Tests ausführen
Schnelles Feedback ohne Vollständigkeit zu opfern

Wer eine wachsende Cypress- oder Playwright-Suite bei jedem Commit komplett ausführt, verliert schnell wertvolle Minuten Feedback-Zeit und CI-Budget. Dieser Artikel zeigt praxisnah, wie Feature-Tags, Dependency-Graphen und Git-Diff-Heuristiken betroffene Tests zuverlässig identifizieren, während geplante Vollläufe weiterhin als Sicherheitsnetz gegen übersehene Regressionen dienen.

12 Min. Lesezeit Selective Testing · Test Selection Cypress · Playwright · CI/CD

1. Warum der volle Suite-Lauf bei jedem Commit nicht skaliert

Eine E2E-Suite, die am Anfang eines Projekts in fünf Minuten durchläuft, wächst mit jedem neuen Feature mit: aus 50 Cypress-Specs werden schnell 500, aus fünf Minuten Laufzeit werden vierzig. Wird die komplette Suite bei jedem Commit oder jedem Push in einen Feature-Branch ausgeführt, wächst die Wartezeit bis zum ersten grünen oder roten Ergebnis proportional mit der Codebasis, nicht mit der Größe der eigentlichen Änderung. Entwickler, die für einen Ein-Zeilen-Fix vierzig Minuten auf die CI warten, verlieren den Fokus, wechseln den Kontext und reviewen Pull Requests seltener zeitnah.

Das Problem verschärft sich mit paralleler CI-Infrastruktur: Mehr Runner beschleunigen zwar die Wall-Clock-Zeit, erhöhen aber die Kosten linear mit der Suite-Größe, ohne das Grundproblem zu lösen. Zusätzlich steigt mit der Anzahl der Tests auch die statistische Wahrscheinlichkeit, dass mindestens ein flakiger Test fehlschlägt: Bei 1000 Specs mit je 0,1 % Flake-Rate schlägt statistisch fast jeder zehnte Lauf mindestens einmal grundlos fehl. Teams beginnen dann, rote Pipelines zu ignorieren oder Tests zu deaktivieren, was den eigentlichen Sicherheitsgewinn der E2E-Suite untergräbt.

2. Tests nach Feature-Bereich taggen: Cypress- und Playwright-Patterns

Der einfachste Einstieg in selektives Testen ist das Taggen von Tests nach Feature-Bereich oder fachlicher Domäne. In Playwright lässt sich ein Tag direkt im Testnamen oder über test.describe mit einem Annotation-String wie @checkout hinterlegen, in Cypress übernimmt das Community-Plugin cypress-grep dieselbe Aufgabe über Test-Titel oder Cypress.env. Über die CLI-Flags --grep beziehungsweise grepTags lässt sich dann gezielt nur die Teilmenge ausführen, die zu einem geänderten Feature-Bereich gehört: Ein Checkout-Bugfix triggert nur @checkout-Tests, keine Kataloglogik.

Tagging ist schnell implementiert und für Menschen sofort lesbar, hat aber eine strukturelle Schwäche: Die Zuordnung ist manuell und driftet mit der Zeit auseinander, wenn Entwickler neue Tests ohne Tag committen oder Code in einen anderen Bereich verschieben, ohne die Tags anzupassen. Ein CI-Check, der ungetaggte Specs blockiert oder Tags gegen ein Verzeichnis-Schema validiert, hält die Tag-Disziplin langfristig aufrecht. Tagging eignet sich am besten als schnelle erste Stufe, kombiniert mit präziseren, automatisierten Mechanismen für höhere Verlässlichkeit.


// tests/checkout/checkout-flow.spec.ts
import { test, expect } from '@playwright/test';

// Tag this spec with its feature area for selective execution
test.describe('Checkout flow @checkout @critical', () => {
  test('customer can complete checkout with saved address @smoke', async ({ page }) => {
    await page.goto('/checkout');
    await page.getByRole('button', { name: 'Place order' }).click();
    await expect(page.getByText('Thank you for your order')).toBeVisible();
  });

  test('checkout blocks submission with invalid payment data', async ({ page }) => {
    await page.goto('/checkout');
    await page.getByLabel('Card number').fill('0000');
    await page.getByRole('button', { name: 'Place order' }).click();
    await expect(page.getByText('Invalid card number')).toBeVisible();
  });
});

3. Dependency-Graph-basierte Testauswahl

Präziser als manuelles Tagging ist eine dependency-graph-basierte Testauswahl: Ein Tool baut aus den Importen und Modulabhängigkeiten des Codes einen Graphen und leitet daraus ab, welche Testdateien transitiv von einer geänderten Quelldatei betroffen sind. Für reine Frontend- oder Node-Codebasen übernehmen Tools wie dependency-cruiser oder madge den Graphenbau, für Magento-Backends mit PHP-Modulen bietet sich stattdessen ein explizites Modul-zu-Test-Manifest an, das Verzeichnispfade auf zugehörige Spec-Dateien abbildet.

Der Vorteil gegenüber Tags: Der Graph bildet reale Code-Abhängigkeiten ab statt menschlicher Einschätzung, wodurch die False-Negative-Rate, also übersehene, tatsächlich betroffene Tests, deutlich sinkt. Der Nachteil ist der initiale Aufwand: Ein Dependency-Graph muss gepflegt, bei Refactorings neu berechnet und gegen tatsächliche Testergebnisse validiert werden, bevor ein Team ihm vertraut. In der Praxis bewährt sich ein hybrider Ansatz, der Tags für schnelle manuelle Selektion und den Graphen als automatisierte, verlässlichere Fallback-Ebene kombiniert.


{
  "modules": {
    "checkout": {
      "sourcePaths": ["src/checkout", "app/code/Mironsoft/Checkout"],
      "specs": ["tests/checkout/checkout-flow.spec.ts", "tests/checkout/payment.spec.ts"]
    },
    "catalog": {
      "sourcePaths": ["src/catalog", "app/code/Mironsoft/Catalog"],
      "specs": ["tests/catalog/product-listing.spec.ts", "tests/catalog/filters.spec.ts"]
    },
    "cart": {
      "sourcePaths": ["src/cart", "app/code/Mironsoft/Cart"],
      "specs": ["tests/cart/add-to-cart.spec.ts", "tests/cart/mini-cart.spec.ts"]
    },
    "core": {
      "sourcePaths": ["src/shared", "app/code/Mironsoft/Core"],
      "specs": ["*"]
    }
  }
}

4. Git-Diff-Heuristiken: Von geänderten Dateien zu betroffenen Tests

Eine niedrigschwellige Alternative zum vollständigen Dependency-Graphen ist eine Git-Diff-Heuristik: Ein Skript ermittelt mit git diff --name-only alle gegenüber dem Ziel-Branch geänderten Dateien und ordnet sie über ein einfaches Pfad-Präfix-Schema den betroffenen Feature-Tags oder Testverzeichnissen zu. Ändert ein Commit ausschließlich Dateien unter src/checkout/, laufen nur @checkout-Tests; betrifft die Änderung ein geteiltes Modul, greift bewusst ein konservativer Fallback auf die volle Suite.

Der entscheidende Designfehler, den viele Teams anfangs machen: Sie mappen Dateien nur auf Verzeichnisebene, ohne transitive Abhängigkeiten zu berücksichtigen. Ein geändertes, gemeinsam genutztes Utility-Modul betrifft dann potenziell Dutzende Feature-Bereiche, die die reine Pfad-Heuristik nicht erkennt. Deshalb sollte jede Git-Diff-Heuristik eine explizite Positivliste kritischer, geteilter Pfade enthalten, bei deren Änderung automatisch die volle Suite statt einer Teilmenge läuft, statt stillschweigend Tests zu überspringen.


#!/usr/bin/env bash
# scripts/select-affected-tests.sh
# Maps changed files against a base branch to affected E2E specs

set -euo pipefail

BASE_BRANCH="${1:-origin/main}"
CHANGED_FILES=$(git diff --name-only "$BASE_BRANCH"...HEAD)

AFFECTED_TAGS=()

while IFS= read -r file; do
  case "$file" in
    src/checkout/*|app/code/*/Checkout/*)
      AFFECTED_TAGS+=("@checkout")
      ;;
    src/catalog/*|app/code/*/Catalog/*)
      AFFECTED_TAGS+=("@catalog")
      ;;
    src/cart/*|app/code/*/Cart/*)
      AFFECTED_TAGS+=("@cart")
      ;;
    src/shared/*|app/code/*/Core/*)
      # Shared/core changes are high risk: fall back to the full suite
      echo "Shared module changed, running full suite"
      exit 0
      ;;
  esac
done <<< "$CHANGED_FILES"

UNIQUE_TAGS=$(printf '%s\n' "${AFFECTED_TAGS[@]}" | sort -u | paste -sd '|')
echo "Running tests matching: ${UNIQUE_TAGS:-@smoke}"
npx playwright test --grep "${UNIQUE_TAGS:-@smoke}"

5. Selektive Tests auf jedem PR, volle Suite nach Zeitplan

Die wirkungsvollste Kombination in der Praxis trennt zwei Zeitachsen bewusst voneinander: Auf jedem Pull Request läuft eine selektive, auf die tatsächliche Änderung zugeschnittene Testmenge, die in wenigen Minuten Feedback liefert und Entwickler nicht aus dem Kontext reißt. Der volle Regressionslauf über alle Specs findet dagegen nach einem festen Zeitplan statt, typischerweise nachts, sowie zusätzlich zwingend vor jedem Merge in den Main-Branch oder vor einem Release-Tag.

Diese Trennung löst den scheinbaren Zielkonflikt zwischen Geschwindigkeit und Vollständigkeit auf: Entwickler erhalten schnelles Feedback auf genau die Änderung, an der sie gerade arbeiten, während das Team als Ganzes weiterhin regelmäßig die vollständige Garantie erhält, dass keine Kombination aus mehreren kleinen PRs eine Regression erzeugt hat, die keine einzelne selektive Auswahl allein hätte erkennen können. Wichtig ist, dass der nächtliche Lauf sichtbar überwacht wird und Fehlschläge nicht stillschweigend im Slack-Kanal untergehen.

6. Das Risiko übersehener Regressionen und wie man es mindert

Selektives Testen hat einen inhärenten blinden Fleck: Eine Änderung kann Seiteneffekte in einem Bereich auslösen, den weder Tags noch Dependency-Graph noch Git-Diff-Heuristik als betroffen erkennen, etwa eine globale CSS-Regel, ein geteilter Zustand im Alpine.js-Store oder eine Änderung an einer Drittanbieter-Bibliothek, die mehrere Feature-Bereiche gleichzeitig berührt. Wer sich ausschließlich auf selektive Läufe verlässt und komplett auf Vollläufe verzichtet, akkumuliert dieses Risiko unbemerkt über Wochen.

Die wirksamste Gegenmaßnahme ist der bereits erwähnte periodische Vollregressionslauf als Sicherheitsnetz, der übersehene Kombinationen zuverlässig auffängt, bevor sie in Produktion landen. Zusätzlich lohnt sich, die Trefferquote der Selektionslogik aktiv zu tracken: Immer wenn ein nächtlicher Vollauf einen Fehler findet, der in der zugehörigen PR-Selektion nicht enthalten war, ist das ein klares Signal, den Dependency-Graphen oder die Pfad-Heuristik nachzuschärfen. Diese Feedback-Schleife macht die Selektionsqualität über Zeit messbar statt einer reinen Vermutung.

7. Tooling-Beispiele: Nx Affected, Turborepo und Custom-Manifeste

Im Monorepo-Umfeld haben sich Werkzeuge wie nx affected und Turborepos Change-Detection-Graph etabliert, die ursprünglich für Build- und Unit-Test-Selektion entwickelt wurden, sich aber ebenso auf E2E-Testauswahl übertragen lassen: Beide Tools berechnen aus dem Projekt-Dependency-Graphen, welche Packages von einer Änderung betroffen sind, und lassen sich über ein Custom-Target so konfigurieren, dass sie statt npm test einen playwright test --grep-Aufruf mit den passenden Tags triggern.

Für Magento- und PHP-lastige Projekte ohne Nx- oder Turborepo-Monorepo-Struktur ist ein handgeschriebenes JSON-Manifest oft die pragmatischere Lösung: Eine einzige Datei bildet Modulverzeichnisse auf zugehörige Spec-Dateien ab und wird von einem einfachen Node- oder Bash-Skript ausgewertet. Der Vorteil gegenüber einem vollautomatischen Graphen ist die Transparenz: Jeder im Team kann die Zuordnung in einer Datei nachvollziehen und pflegen, ohne ein zusätzliches Analyse-Tool zu verstehen oder zu debuggen.


# Run only checkout-tagged specs with Playwright
npx playwright test --grep "@checkout"

# Run smoke tests across all feature areas for a fast PR gate
npx playwright test --grep "@smoke"

# Cypress equivalent using the cypress-grep plugin
npx cypress run --env grepTags="@checkout"

# Exclude flaky/quarantined specs while still running the affected set
npx playwright test --grep "@checkout" --grep-invert "@quarantine"

8. Praktische CI-Pipeline: Schnelle PR-Checks plus nächtlicher Vollregressionslauf

Eine belastbare CI-Pipeline für E2E-Tests trennt die selektive PR-Prüfung technisch vom vollständigen Regressionslauf in zwei eigenständige Jobs. Der PR-Job checkt den Branch mit vollständiger Git-Historie aus, berechnet über das Diff-Skript die betroffenen Tags und führt nur diese aus, typischerweise in unter zehn Minuten abgeschlossen. Der zweite Job läuft ausschließlich per Cron-Zeitplan oder als Pflicht-Gate vor dem Merge in Main und führt die komplette, üblicherweise in mehrere Shards aufgeteilte Suite aus.

Sharding ist bei Vollläufen entscheidend, um die Laufzeit trotz vollständiger Abdeckung im Rahmen zu halten: Playwrights --shard=N/M-Flag oder Cypress' Parallelisierung über mehrere Runner verteilen die Gesamtmenge der Specs auf parallele CI-Maschinen. Schlägt der nächtliche Vollauf fehl, sollte das Team automatisch benachrichtigt werden, etwa über einen dedizierten Slack-Kanal oder ein GitHub-Issue, statt den Fehlschlag erst beim nächsten manuellen Blick auf die CI-Historie zu bemerken.


# .github/workflows/e2e.yml
name: E2E Tests

on:
  pull_request:
    branches: [main]
  schedule:
    - cron: '0 2 * * *'  # Nightly full regression run at 02:00 UTC

jobs:
  selective-pr-tests:
    if: github.event_name == 'pull_request'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - run: npm ci
      - name: Run only affected E2E specs
        run: ./scripts/select-affected-tests.sh origin/main

  full-regression:
    if: github.event_name == 'schedule'
    runs-on: ubuntu-latest
    strategy:
      matrix:
        shard: [1, 2, 3, 4]
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - name: Run full E2E suite (sharded)
        run: npx playwright test --shard=${{ matrix.shard }}/4

9. Selektive Teststrategien im Vergleich

Jede der vorgestellten Selektionsstrategien hat ein spezifisches Schwachstellen-Muster und einen bewährten Gegenpol, mit dem sich das Risiko in der Praxis kontrollieren lässt. Die folgende Übersicht fasst zusammen, worauf es bei jeder Strategie ankommt.

Strategie Schwäche Empfohlenes Pattern Nutzen
Voller Suite-Lauf bei jedem Commit Skaliert nicht, Laufzeit wächst mit der Codebasis Nur nächtlich oder vor Release ausführen Vollständige Regressionssicherheit ohne PR-Blockade
Manuelles Tagging Tags driften ohne Disziplin auseinander CI-Check gegen Verzeichnis-Schema validieren Schnelle, menschlich lesbare Selektion
Reine Git-Diff-Heuristik Übersieht transitive Abhängigkeiten Mit Dependency-Graph kombinieren Geringer Implementierungsaufwand
Dependency-Graph ohne Fallback Hoher initialer Pflegeaufwand Konservativen Vollsuite-Fallback für Core-Module definieren Niedrige False-Negative-Rate
Ausschließlich selektive Läufe Übersehene Regressionen akkumulieren unbemerkt Periodischen Vollregressionslauf als Sicherheitsnetz einplanen Messbare Selektionsqualität über Zeit

In der Praxis kombinieren die erfolgreichsten Setups mehrere dieser Strategien: Tags für die schnelle manuelle Kategorisierung, einen Dependency-Graphen oder ein Manifest für Präzision, Git-Diff-Heuristiken als schnellen ersten Filter und einen periodischen Vollregressionslauf als nicht verhandelbares Sicherheitsnetz gegen alles, was die automatisierte Selektion übersieht.

Mironsoft

E2E-Testautomatisierung, CI/CD und Selective Testing für Magento-Shops

Selective Testing professionell einführen?

Wir analysieren eure Cypress- oder Playwright-Suite, bauen Feature-Tagging und Dependency-Graphen auf und richten eine CI-Pipeline ein, die schnelle PR-Checks mit nächtlichen Vollregressionsläufen sinnvoll kombiniert.

Selective-Testing-Audit

Analyse der Suite-Laufzeit und Priorisierung nach Feedback-Impact

Tagging & Dependency-Graph

Feature-Tags, Manifeste und Git-Diff-Heuristiken sauber implementieren

CI-Pipeline-Setup

Selektive PR-Checks und gesharded Vollläufe in GitHub Actions/GitLab CI

10. Zusammenfassung

Selective Testing löst ein konkretes Skalierungsproblem: Je größer eine E2E-Suite wird, desto teurer und langsamer wird es, sie bei jedem Commit vollständig auszuführen, ohne dass der Erkenntnisgewinn proportional mitwächst. Feature-Tags liefern einen schnellen Einstieg, Dependency-Graphen und Manifeste erhöhen die Präzision, und Git-Diff-Heuristiken verbinden beides mit der tatsächlichen Änderung eines Commits oder Pull Requests.

Entscheidend für den langfristigen Erfolg ist die bewusste Kombination aus schnellen selektiven PR-Checks und einem nicht verhandelbaren, regelmäßigen Vollregressionslauf als Sicherheitsnetz. Wer die Trefferquote der Selektionslogik aktiv misst und bei jedem übersehenen Fehler nachschärft, baut über Zeit ein Testsystem, das sowohl schnell als auch verlässlich bleibt, statt zwischen beiden Zielen wählen zu müssen.

Selective Testing für E2E-Suiten - Das Wichtigste auf einen Blick

Feature-Tagging

@checkout, @catalog & Co. für schnelle, menschlich lesbare Selektion über --grep.

Dependency-Graph

Modul-zu-Test-Manifest oder Graph-Tooling für präzise, automatisierte Zuordnung.

PR vs. Vollauf

Selektive Tests auf jedem PR, vollständige Suite nächtlich und vor jedem Release.

Sicherheitsnetz

Periodische Vollregressionsläufe fangen übersehene Regressionen zuverlässig auf.

11. FAQ: Selective Testing für E2E-Suiten

1Was ist Selective Testing und warum brauche ich es?
Führt bei jeder Codeänderung nur die tatsächlich betroffenen E2E-Tests aus, statt die komplette Suite. Hält die Feedback-Zeit auf Pull Requests niedrig, auch wenn die Gesamtsuite auf hunderte oder tausende Specs wächst.
2Ab welcher Suite-Größe lohnt sich Selective Testing?
Faustregel: Sobald ein voller Lauf über zehn Minuten dauert oder Entwickler auf CI-Ergebnisse warten statt weiterzuarbeiten. Bei Suiten unter fünf Minuten überwiegt meist der Implementierungsaufwand.
3Wie taggt man Tests nach Feature-Bereich in Cypress/Playwright?
In Playwright via test.describe-Annotation wie @checkout plus --grep-Flag. In Cypress übernimmt das Plugin cypress-grep dieselbe Aufgabe über Test-Titel und grepTags.
4Was ist dependency-graph-basierte Testauswahl?
Ein Tool oder Manifest bildet Abhängigkeiten zwischen Quelldateien und Tests ab und berechnet bei Änderungen automatisch alle transitiv betroffenen Specs statt manueller Tags.
5Wie funktioniert eine Git-Diff-basierte Testzuordnung?
Ein Skript liest git diff --name-only aus und ordnet Pfade per Präfix-Schema Feature-Tags zu, inklusive konservativem Vollsuite-Fallback bei geteilten Modulen.
6Sollte ich komplett auf volle Suite-Läufe verzichten?
Nein. Selektive Läufe sollten immer durch periodische Vollregressionsläufe ergänzt werden, typischerweise nächtlich und vor jedem Release.
7Wie mindere ich das Risiko übersehener Regressionen?
Über regelmäßige Vollregressionsläufe als Sicherheitsnetz plus aktives Tracking der Selektionsqualität, um Tags, Graph oder Heuristik gezielt nachzuschärfen.
8Welche Tools helfen bei der Testauswahl (Nx, Turborepo)?
Nx affected und Turborepos Change-Detection-Graph für Monorepos; für Nicht-Monorepo-Projekte ist ein eigenes JSON-Manifest oft pragmatischer.
9Wie sieht eine gute CI-Pipeline mit Selective Testing aus?
Zwei getrennte Jobs: ein schneller selektiver PR-Job und ein geplanter, gesharded Vollregressionslauf mit Benachrichtigung bei Fehlschlägen.
10Was ist der Unterschied zwischen PR-Checks und nächtlichen Vollläufen?
PR-Checks laufen selektiv und schnell für konkretes Feedback. Nächtliche Vollläufe decken die komplette Suite ab und dienen als Sicherheitsnetz gegen PR-übergreifende Regressionen.