← Alle Beiträge

Eine Testautomatisierung-Strategie, die wirklich funktioniert

Matthias Bruns · · 5 Min. Lesezeit
testing automation backend architecture ci-cd

Die meisten Test-Strategien scheitern an den Nahtstellen

Teams shippen mit 90% Unit-Test-Coverage und werden trotzdem in Production kalt erwischt. Der Grund ist immer derselbe: Die Tests verifizieren einzelne Komponenten isoliert, aber niemand testet, wie diese Komponenten zusammenspielen.

Du kennst das. Ein Service ändert sein Response-Format. Die Unit-Tests des Consumers fangen es nicht, weil sie die Dependency mocken. Die Integration-Test-Suite — falls sie existiert — läuft nachts, und keiner schaut hin, bis Freitagmittag etwas kaputtgeht.

Eine echte Testautomatisierung-Strategie optimiert nicht auf Coverage-Zahlen. Sie optimiert auf Vertrauen pro CI-Minute.

Pyramide, Trophy und was tatsächlich zählt

Mike Cohn hat die Testautomatisierung-Pyramide vor über zehn Jahren eingeführt: viele Unit-Tests unten, weniger Integration-Tests in der Mitte, eine dünne E2E-Schicht oben. Die Logik war ökonomisch — Unit-Tests waren schnell und günstig, E2E-Tests langsam und fragil.

Kent C. Dodds schlug später die Testing Trophy vor und argumentierte, dass Integration-Tests den höchsten Return on Investment liefern. Sein Leitsatz: “Write tests. Not too many. Mostly integration.

Beide Modelle sind nützliche Daumenregeln, aber keine Strategie. Eine Strategie beantwortet: Was testen wir, auf welcher Ebene, und was lassen wir bewusst weg?

Unser Framework:

  1. Unit-Tests für pure Logik — Berechnungen, Transformationen, Validierungsregeln. Keine Dependencies? Unit-Test.
  2. Integration-Tests für Service-Grenzen — API-Contracts, Datenbank-Queries, Message-Handler. Hier leben die meisten Bugs.
  3. E2E-Tests nur für kritische User-Pfade — Checkout, Login, die drei Flows, die Umsatz generieren.
  4. Statische Analyse als Fundament — TypeScript Strict Mode, Linter, Formatter. Eliminiert ganze Bug-Kategorien, bevor Tests überhaupt laufen.

Integration-Tests: Hier liegt der ROI

Die größte Lücke in den meisten Test-Suites ist die Integrationsebene. Teams überspringen sie komplett oder schreiben Integration-Tests, die eigentlich nur Unit-Tests mit Extra-Aufwand sind.

Ein sauberer Integration-Test für einen Backend-Service:

  • Startet die echte Datenbank (nutze Testcontainers — läuft problemlos in CI)
  • Ruft den realen HTTP-Endpoint oder die gRPC-Methode auf
  • Prüft die tatsächliche Response: Status-Codes, Headers, Body-Shape
  • Räumt nach sich auf

In Go sieht das aus wie ein TestMain, das einen Postgres-Container startet, Migrationen ausführt und am Ende aufräumt. In Node.js/TypeScript ist es ein beforeAll, das den Server gegen eine echte Datenbank hochfährt.

Die Kernregel: Mocke an der Systemgrenze, nicht innerhalb des Systems. Mocke die externe Payment-API. Mocke nicht Dein eigenes Repository-Layer.

Datenbank-Queries testen

Wenn Du ein ORM oder einen Query-Builder nutzt, verifizieren Deine Unit-Tests nicht das tatsächliche SQL. Die Query könnte syntaktisch falsch sein, oder das ORM generiert etwas Unerwartetes.

Teste gegen eine echte Datenbank:

func TestCreateUser(t *testing.T) {
    db := setupTestDB(t) // Testcontainers
    repo := NewUserRepository(db)
    ctx := context.Background()

    user, err := repo.Create(ctx, CreateUserInput{
        Email: "test@example.com",
        Name:  "Test User",
    })

    assert.NoError(t, err)
    assert.NotEmpty(t, user.ID)
    assert.Equal(t, "test@example.com", user.Email)
}

Das fängt Schema-Mismatches, Constraint-Verletzungen und Migrationsfehler, die kein Mocking der Welt aufdeckt.

E2E-Tests: Weniger ist mehr

E2E-Tests sind teuer zu schreiben, langsam in der Ausführung und anfällig für Flakiness. Aber für kritische Pfade sind sie unersetzlich.

Das moderne Tooling hat sich drastisch verbessert. Playwright handhabt Cross-Browser-Testing, wartet automatisch auf Elemente und bietet Tracing zum Debugging von Fehlern. In 2026 ist es die klare Wahl für Web-E2E.

Regeln für E2E-Tests, die kein Wartungsalptraum werden:

  1. Teste User-Journeys, keine Features. “User registriert sich, erstellt ein Projekt, lädt einen Teamkollegen ein” — nicht “der Signup-Button ändert die Farbe beim Hover.”
  2. Nutze realistische, aber kontrollierte Daten. Seed die Datenbank vor jedem Test. Verlasse Dich nie auf Shared State zwischen Tests.
  3. Setze ein hartes Limit. Wir deckeln E2E-Suites bei 20 Minuten. Dauert es länger, testest Du zu viel auf dieser Ebene.
  4. Quarantänisiere flaky Tests sofort. Ein flaky E2E-Test, den alle ignorieren, ist schlimmer als kein Test. Markieren, fixen oder löschen.

CI-Integration: Geschwindigkeit ist ein Feature

Eine Test-Suite, die 45 Minuten braucht, wird nicht bei jedem Push ausgeführt. Entwickler batchen Änderungen, überspringen die Suite und mergen auf Hoffnung.

Ziel-CI-Zeiten:

  • Lint + Type-Check: Unter 2 Minuten
  • Unit-Tests: Unter 3 Minuten
  • Integration-Tests: Unter 10 Minuten (parallelisiere nach Test-Package)
  • E2E-Tests: Unter 15 Minuten (nur bei PRs gegen main, nicht bei jedem Commit)

Parallelisiere aggressiv. Die meisten CI-Provider geben Dir mehrere Worker. Splitte Deine Integration-Suite nach Package oder Modul und führe sie parallel aus.

Cache smart: Datenbank-Container-Images, npm/Go-Module-Caches, vorgebaute Test-Fixtures. Jede eingesparte Sekunde akkumuliert über hunderte Runs.

Die Strategie auf einer Seite

EbeneWas testenToolingWann ausführen
StatischTypen, Lint-Regeln, FormatierungTypeScript strict, ESLint, go vetJeder Commit
UnitPure Funktionen, Business-LogikJest, go test, VitestJeder Commit
IntegrationAPI-Grenzen, DB-Queries, Message-HandlerTestcontainers, supertest, httptestJeder Commit
ContractService-zu-Service-AgreementsPactBei PR + Provider-Deploy
E2EKritische User-Journeys (3–5 max)PlaywrightPR auf main

Das ist kein theoretisches Modell. Es ist das Setup, das wir auf Produktions-Services fahren. Unsere Pipeline ohne E2E bleibt unter 15 Minuten; die vollständige PR-Pipeline bleibt durch Parallelisierung ebenfalls schnell. Das Vertrauenslevel reicht, um auf Grün zu deployen.

Fang dort an, wo es wehtut

Versuch nicht, die perfekte Test-Suite in einem Sprint aufzubauen. Starte mit der Frage: Woher kamen unsere letzten drei Production-Bugs?

Waren es Integrationsprobleme — investiere in Integration-Tests. Waren es Regressionen in User-Flows — ergänze E2E für genau diese Flows. Waren es Typfehler — schalte den Strict Mode ein.

Die beste Testautomatisierung-Strategie ist die, die die Bugs verhindert, die Du tatsächlich shippst.

Lesebarkeit

Schriftgröße