k6 + BDD + CI/CD: 4 Fliegen mit einer Klappe [2026]

Aktualisiert: 19. Mai 2026

Performance-Tester schreiben JavaScript-Skripte. Fach-Tester schreiben Cucumber-Features. Niemand versteht den anderen. Dabei testen beide dasselbe Produkt, nur in zwei getrennten Welten.

Es geht auch anders. Mit k6, Cucumber und GitHub Actions baust du ein Setup, in dem Gherkin die gemeinsame Sprache ist. Performance-Tests werden lesbar, Stakeholder-Reports automatisch und die CI/CD-Pipeline grün. Vier Disziplinen in einem Workflow: API-Tests, Performance-Tests, BDD-Lesbarkeit und CI/CD-Automation.

In diesem Praxis-Leitfaden zeige ich dir, wie das konkret funktioniert. Du bekommst lauffähigen Code für Feature-Files, Step-Definitions und das GitHub-Actions-Workflow-YAML. Wir nutzen k6-cucumber-steps als Bridge und die neue Assertions-API aus k6 2.0 (verfügbar seit Mai 2026).

Inhaltsverzeichnis

Warum BDD und Performance Testing mit k6 zusammen denken?

Die typische Trennung sieht so aus: Das BDD-Team schreibt Gherkin-Features für Funktionalität. Das Performance-Team schreibt k6-JavaScript für Lasttests. Beide Welten produzieren ihre eigenen Reports, ihre eigene Test-Dokumentation und ihre eigenen Akzeptanzkriterien.

Trennung zwischen BDD-Funktionaltests und Performance-Tests
BDD und Performance Testing leben in vielen Teams parallel, ohne gemeinsame Brücke

Das Problem: Product Owner und Stakeholder verstehen Gherkin. Sie verstehen kein Performanztest (Performance-Test)-Skript mit http.get(), Thresholds und VU-Konfiguration. Das Resultat: Performance-Anforderungen landen in JIRA als „<500ms p95"-Akzeptanzkriterium, aber niemand weiß, ob der Test dieses Kriterium wirklich abbildet.

Die Brücke heißt BDD-Performance-Testing. Du schreibst deine Performance-Szenarien als Gherkin-Features. Stakeholder lesen die Features wie Akzeptanzkriterien. Eine Bridge wie k6-cucumber-steps übersetzt die Features in lauffähige k6-Skripte. Das Ergebnis: Ein einziges Artefakt, das funktionale UND performance-relevante Akzeptanzkriterien abbildet.

Vier Disziplinen verschmelzen zu einem Workflow:

  1. API-Tests: Funktionalität jedes Endpunkts (Status-Codes, Response-Shape)
  2. Performance-Tests: Antwortzeiten unter Last (Smoke, Load, Stress, Spike, Soak)
  3. BDD-Lesbarkeit: Gherkin als gemeinsame Sprache für PO, Tester, Entwickler
  4. CI/CD-Automation: Tests laufen in GitHub Actions, Reports landen automatisch im Stakeholder-Kanal

Genau das verspricht die Schlagzeile „4 Fliegen mit einer Klappe". In den folgenden Abschnitten zeige ich dir, wie das konkret aussieht.

k6 in 60 Sekunden

Wenn du schon k6-Praxis hast, überspring diesen Abschnitt. Wenn nicht: Hier die Kurz-Version. Den vollständigen Praxis-Leitfaden findest du in unserem k6 Lasttest-Tutorial. Dort decken wir Installation, Test-Pyramide, alle 5 Test-Typen, Scenarios und Metriken im Detail ab.

k6 ist ein Open-Source-Lasttest-Tool von Grafana Labs. Du schreibst Tests in JavaScript (ES6+), führst sie über die Kommandozeile aus und bekommst aggregierte Metriken zurück. Die Kernkonzepte in 4 Begriffen:

  • VUs (Virtual Users): simulierte parallele Nutzer. 10 VUs bedeutet 10 gleichzeitige Sessions.
  • Scenarios: definieren wie Last erzeugt wird. Stages für Ramp-up, konstante Last oder Spike-Pattern.
  • Thresholds: Pass/Fail-Gates. „p(95) der Antwortzeiten muss unter 500ms liegen" als Threshold abgebildet, k6 setzt am Test-Ende den Exit-Code entsprechend.
  • Metrics: built-in Werte wie http_req_duration, http_reqs, vus, plus eigene Custom-Metrics (Counter, Gauge, Trend, Rate).

Neu in k6 2.0 (Quelle: Grafana Labs Release-Blog Mai 2026): Eine erweiterte Assertions-API mit expect()-Stil, native OpenTelemetry-Ausgabe, ein konsolidierter Extensions-Katalog und Subcommand-Extensions unter k6 x für KI-gestützte Test-Workflows. Genau diese Assertions-API werden wir später als BDD-Brücke nutzen.

BDD als gemeinsame Sprache

Behavior Driven Development ist mehr als „Tests in englischer Sprache schreiben". Es ist eine Disziplin, in der Product Owner, Tester und Entwickler gemeinsam Akzeptanzkriterien als ausführbare Spezifikation formulieren. Die Detailgrundlagen findest du im BDD-Cucumber-Tutorial.

API-Testing-Workflow als Schritt-für-Schritt-Diagramm
Der typische API-Testing-Workflow lässt sich 1:1 in Gherkin-Features übersetzen

Das Format heißt Gherkin. Ein Feature beschreibt einen Anwendungsfall, jedes Szenario darin folgt dem Given/When/Then-Muster:

  • Given beschreibt den Ausgangszustand (z.B. „die User-API ist erreichbar")
  • When beschreibt die Aktion (z.B. „ich rufe GET /users/1 auf")
  • Then beschreibt das erwartete Ergebnis (z.B. „der Status-Code ist 200")

Für reine Funktional-Tests setzen viele Teams Cucumber.js, SpecFlow oder ähnliche Frameworks ein. Für Performance-Tests fehlte bisher die Brücke. Performance-Akzeptanzkriterien wie „p(95) < 500ms unter 100 VUs" landeten in Dokumentation, nicht in ausführbaren Features. Genau diese Lücke schließt k6-cucumber-steps.

k6-cucumber-steps: die Bridge

Seit Februar 2026 gibt es ein CLI-Tool, das Gherkin-Features direkt in lauffähige k6-Skripte übersetzt. Es heißt k6-cucumber-steps und ist via npm verfügbar (Quelle: Tutorial von Paschal Enyimiri, Februar 2026).

Die Bridge funktioniert deklarativ: Du annotierst deine Gherkin-Szenarien mit Tags wie @vus:10, @duration:1m oder @stages:0s-0,30s-10,60s-50. Das Tool parst die Tags und generiert daraus die passende k6-Konfiguration mit Scenarios, Thresholds und Stages.

Installation und Projekt-Setup in zwei Befehlen:

Listing 1: Installation und Projekt-Setup k6-cucumber-steps
npm install -g k6-cucumber-steps
npx k6-cucumber-steps init my-k6-bdd-project

Ein Feature-File mit Tags sieht dann so aus:

Listing 2: Gherkin-Feature für User-API Performance unter Smoke-Last
@smoke @vus:10 @duration:1m @threshold:http_req_duration=p(95)<500
Feature: User-API Performance unter Smoke-Last
  Background:
    Given die k6-Base-URL ist "https://api.example.com"

  Scenario: GET /users/1 antwortet unter Smoke-Last
    When ich einen GET-Request auf "/users/1" sende
    Then ist der Response-Status "200"
    And ist die Antwortzeit unter 500ms

  Scenario: GET /users-Liste antwortet unter Smoke-Last
    When ich einen GET-Request auf "/users" sende
    Then ist der Response-Status "200"
    And enthält die Response mindestens 10 Einträge

Das ist lesbar für Product Owner. Es ist ausführbar als Performance-Test. Es enthält Akzeptanzkriterien (200-Status, <500ms p95) als integralen Bestandteil. Keine separate Dokumentation, kein „bitte glaub mir, das ist getestet".

Setup-Praxis: Gherkin-Feature zu k6-Skript

Schauen wir uns ein konkretes Setup an. Drei Dateien reichen für ein lauffähiges BDD-Performance-Setup: das Feature-File, die Step-Definitions in TypeScript und die k6-Konfiguration.

k6 Test-Setup mit Gherkin-Brücke
k6-cucumber-steps verbindet Gherkin-Features mit der k6-Runtime

Die Step-Definitions sehen so aus:

Listing 3: Step-Definitions in TypeScript
// step-definitions/api-steps.ts
import { Given, When, Then } from 'k6-cucumber-steps';
import http from 'k6/http';
import { check } from 'k6';

let baseUrl: string;
let response: any;

Given('die k6-Base-URL ist {string}', (url: string) => {
  baseUrl = url;
});

When('ich einen GET-Request auf {string} sende', (path: string) => {
  response = http.get(`${baseUrl}${path}`);
});

Then('ist der Response-Status {string}', (expected: string) => {
  check(response, {
    [`status is ${expected}`]: (r) => r.status === parseInt(expected, 10),
  });
});

Then('ist die Antwortzeit unter {int}ms', (max: number) => {
  check(response, {
    [`response time < ${max}ms`]: (r) => r.timings.duration < max,
  });
});

Test-Ausführung erfolgt mit einem einzigen Kommando:

Listing 4: Test-Ausführung mit k6-cucumber-steps
npx k6-cucumber-steps run features/ --output json=results.json

Das Tool generiert das k6-Skript on-the-fly, führt es aus und liefert sowohl die k6-Metriken als auch einen Cucumber-Style-Report. Damit hast du beide Welten in einem Run. Beide Reports zur Hand für Engineering und Stakeholder.

Thresholds als Akzeptanzkriterien

Hier wird die Brücke zwischen ISTQB-Welt und k6-Welt konkret. Ein Abnahmetest (Akzeptanztest) prüft, ob das System die definierten Akzeptanzkriterien erfüllt. Performance-Akzeptanzkriterien sind in k6 als thresholds abbildbar.

Typische Performance-Akzeptanzkriterien aus User Stories:

  • „Die Suche antwortet bei 95% der Anfragen unter 500ms" → http_req_duration: ['p(95)<500']
  • „Fehlerrate bei 100 VUs liegt unter 1%" → http_req_failed: ['rate<0.01']
  • „Der Service hält 1000 Requests pro Sekunde durch" → http_reqs: ['rate>1000']

In k6 2.0 kannst du diese Akzeptanzkriterien auch mit der neuen Assertions-API ausdrücken. Sie kommt in zwei Varianten: non-retrying für statische Werte und auto-retrying für Bedingungen, die erst nach einer Wartezeit erfüllt werden müssen.

Listing 5: k6 2.0 Assertions-API mit expect()
// k6 2.0 Assertions-API
import { expect } from 'k6/expect';

export default function () {
  const res = http.get('https://api.example.com/users/1');

  // non-retrying: sofortige Auswertung
  expect(res.status).toBe(200);
  expect(res.timings.duration).toBeLessThan(500);

  // auto-retrying: wartet bis Bedingung erfüllt oder Timeout
  expect.poll(() => res.body).toContain('"id":1');
}

Das Pass/Fail-Gate ist damit deklarativ definiert. Wenn ein Threshold reißt, beendet k6 den Test-Run mit Exit-Code 99 (statt 0). Genau dieser Exit-Code wird gleich in der CI/CD-Pipeline zum Quality Gate.

CI/CD-Pipeline mit GitHub Actions

Ein Test, der nur lokal läuft, existiert nicht.

Dieser Satz hat sich in unzähligen Projekten bewahrheitet. Manuelle Performance-Tests auf dem Entwickler-Laptop sind besser als nichts, aber nur knapp. Erst die Integration in die CI/CD-Pipeline macht aus dem Performance-Test ein verlässliches Quality Gate. GitHub Actions ist dafür unser Default-Setup (Details im GitHub-Actions-Tutorial).

API-Testing und Performance-Testing zusammen in der CI/CD-Pipeline
Ein konsolidierter Workflow für API- und Performance-Tests in der Pipeline

Hier das vollständige Workflow-YAML:

Listing 6: GitHub-Actions-Workflow für k6 BDD-Performance-Tests
# .github/workflows/k6-bdd-performance.yml
name: k6 BDD Performance Tests

on:
  pull_request:
    branches: [main]
  schedule:
    - cron: '0 2 * * *'   # nightly Soak-Run

jobs:
  bdd-performance:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install k6-cucumber-steps
        run: npm install -g k6-cucumber-steps

      - name: Install k6 2.0
        run: |
          sudo gpg -k
          sudo gpg --no-default-keyring --keyring /usr/share/keyrings/k6-archive-keyring.gpg \
            --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69
          echo "deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] https://dl.k6.io/deb stable main" \
            | sudo tee /etc/apt/sources.list.d/k6.list
          sudo apt-get update && sudo apt-get install -y k6

      - name: Run BDD Performance Suite
        run: npx k6-cucumber-steps run features/ --output json=k6-results.json --cucumber-report cucumber.json

      - name: Upload k6 Results
        uses: actions/upload-artifact@v4
        with:
          name: k6-results
          path: |
            k6-results.json
            cucumber.json

      - name: Comment PR with Threshold Summary
        if: github.event_name == 'pull_request'
        uses: actions/github-script@v7
        with:
          script: |
            const fs = require('fs');
            const k6 = JSON.parse(fs.readFileSync('k6-results.json'));
            const summary = `## k6 BDD Performance Report\n` +
              `- p(95) Duration: ${k6.metrics.http_req_duration.values['p(95)']}ms\n` +
              `- Error Rate: ${(k6.metrics.http_req_failed.values.rate * 100).toFixed(2)}%\n` +
              `- Total Requests: ${k6.metrics.http_reqs.values.count}`;
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: summary
            });

Der Workflow läuft bei jedem Pull Request gegen main und nachts als Soak-Run (Schedule via Cron). Bei reißenden Thresholds wird der Job rot, der PR-Merge blockiert. Engineering bekommt sofortiges Feedback, Reviewer sehen die p(95)-Latenz direkt im PR-Kommentar.

Reporting: BDD-Output und k6-Metriken konsolidieren

Mit dem Workflow hast du zwei JSON-Outputs: k6-results.json mit den Performance-Metriken und cucumber.json mit dem BDD-Pass/Fail-Status pro Szenario. Beide Reports brauchen unterschiedliche Stakeholder:

  • Engineering will Performance-Trends (Latenz-Histogramme, Failure-Rates, Throughput)
  • Product Owner wollen Pass/Fail pro Akzeptanzkriterium (welche Features bestanden, welche nicht?)
  • Stakeholder wollen die Quintessenz auf einer Folie (grün/rot, Trend gegenüber letzter Woche)

Ein einfaches jq-Skript baut aus beiden Outputs ein konsolidiertes Dashboard-JSON:

Listing 7: Reporting-Konsolidierung mit jq (k6-Metriken + BDD-Output)
jq -s '{
  scenarios_total: .[1].scenarios | length,
  scenarios_passed: [.[1].scenarios[] | select(.status == "passed")] | length,
  p95_duration_ms: .[0].metrics.http_req_duration.values."p(95)",
  error_rate_pct: (.[0].metrics.http_req_failed.values.rate * 100),
  total_requests: .[0].metrics.http_reqs.values.count,
  threshold_violations: [.[0].thresholds | to_entries[] | select(.value.ok == false) | .key]
}' k6-results.json cucumber.json > report-consolidated.json

Mit k6 2.0 wird das noch eleganter: Die native OpenTelemetry-Ausgabe kann Metriken direkt in Grafana, Tempo, Jaeger oder andere OTel-Collectors streamen. Das eigene jq-Skript wird damit überflüssig, sobald deine Observability-Plattform OTel spricht. Stakeholder-Dashboards in Grafana zeigen Performance-Trend und BDD-Acceptance-Rate auf einer einzigen Pinnwand.

Tool-Vergleich: k6, JMeter, Locust für BDD-Setups

Nicht jedes Team kann oder will mit k6 starten. Hier der Vergleich der drei populärsten Performance-Tools im Hinblick auf BDD-Tauglichkeit:

Kriteriumk6 (2.0)JMeterLocust
BDD-Bridge verfügbark6-cucumber-steps (CLI)Maven/Gradle-Plugins, schwergewichtiglocust-cucumber, weniger aktiv
Test-SpracheJavaScript/TypeScriptXML + GroovyPython
Cloud-ModusGrafana Cloud k6 nativBlazeMeter, Octoperf, kostenpflichtigLocust Cloud (Beta)
OpenTelemetry-Outputnativ in 2.0nur über Pluginsexperimentell
GitHub Actions Integrationoffizielle k6-ActionCustom-WorkflowCustom-Workflow
Lernkurve für BDD-Teamsflach (JS verbreitet)steil (XML-Welt)mittel
Reifegrad2.0 GA Mai 2026seit 2001 etabliertseit 2011 etabliert

Detail-Vergleiche findest du im JMeter-Tutorial und im API-Testing-Tools-Vergleich.

Für reine BDD-Setups ist k6 die klarste Wahl: JavaScript-Stack, lebendige Bridge zu Cucumber, native CI/CD-Integration, OTel-Output ohne Plugin-Bastelei. JMeter bleibt stark bei Enterprise-Setups mit XML-First-Kultur. Locust ist eine Option für reine Python-Teams.

Fazit: 4 Fliegen mit einer Klappe

API-Testing als Service mit BDD und Performance-Komponente
BDD, k6-Performance und CI/CD-Automation als integrierter Service-Stack

Das Setup k6 + Cucumber + GitHub Actions löst ein Strukturproblem, das viele Teams seit Jahren mit sich tragen: getrennte Welten für Funktional- und Performance-Tests, getrennte Reports, getrennte Akzeptanzkriterien. Mit Gherkin als gemeinsamer Sprache verschmelzen die Welten.

Wann lohnt sich das Setup wirklich?

  • Gemischtes Team aus Product Owner, Tester, Entwickler mit etabliertem BDD-Workflow
  • Stakeholder-Reporting ist Pflicht und Performance-Anforderungen stehen in den User Stories
  • CI/CD-Pipeline existiert und Quality Gates sind gewollt

Wann lohnt es sich nicht?

  • Reines Engineering-Performance-Testing ohne Stakeholder-Reporting (dann ist k6 direkt mit JavaScript besser)
  • Performance-Tests ohne klare Akzeptanzkriterien (dann ist Profiling die richtige Disziplin, nicht Lasttest)
  • Single-Person-Setups, in denen die BDD-Lesbarkeit niemanden adressiert

Vier Fliegen mit einer Klappe: das funktioniert, wenn die Voraussetzungen passen. Wenn du Unterstützung beim Aufsetzen einer solchen Pipeline brauchst, sprich uns an: Unser QLoad-Service bringt das Setup in dein Projekt.

Performance Testing als Service: QLoad bringt Lasttest-Expertise, Pipeline-Integration und BDD-Reporting in dein Projekt. QLoad kennenlernen →

FAQ: k6 + BDD + CI/CD

Wie funktioniert k6 mit Cucumber zusammen?

k6-cucumber-steps ist ein npm-CLI-Tool, das Gherkin-Feature-Files parst und daraus k6-TypeScript-Skripte generiert. Es läuft eigenständig (keine xk6-Extension nötig) und unterstützt Gherkin-Tags wie @vus, @duration, @stages und @threshold für die k6-Konfiguration. BDD-Grundlagen siehe Cucumber-Tutorial.

Brauche ich xk6-Extensions für BDD?

Nein. k6-cucumber-steps läuft als separates CLI-Tool ohne k6-Recompilation. Wenn du dennoch tiefer in Extensions einsteigen willst (z.B. eigene Protokolle), ist xk6 das offizielle Extension-Toolkit, für reine BDD-Setups aber überdimensioniert. Mehr zu k6 selbst im k6-Lasttest-Leitfaden.

Wie unterscheidet sich das von Postman-API-Tests?

Postman fokussiert auf funktionale API-Tests mit Collections und Newman als CLI. k6 + BDD fokussiert auf Performance unter Last mit Akzeptanzkriterien als integralem Bestandteil. Für reine Funktionalität (Status-Codes, Schema-Validierung, Auth-Flows) bleibt Postman die schlanke Wahl. Siehe Postman-Tutorial.

Kann ich Thresholds als BDD-Akzeptanzkriterien einsetzen?

Ja, das ist sogar einer der Hauptvorteile. k6-Thresholds (http_req_duration: ['p(95)<500']) sind deklarative Pass/Fail-Gates, die exakt User-Story-Akzeptanzkriterien abbilden. Mit der k6 2.0 Assertions-API geht das noch eleganter über expect(). Die CI/CD-Pipeline verhindert dann den Merge, wenn ein Kriterium reißt.

Wie integriere ich das in GitHub Actions?

Du brauchst drei Steps: k6 installieren (offizielles Debian-Repo), k6-cucumber-steps via npm installieren, und den Run-Befehl ausführen. Das vollständige Workflow-YAML findest du im Abschnitt CI/CD-Pipeline oben. Weitere GHA-Grundlagen im GitHub-Actions-Tutorial.

Welche Performance-Tests deckt das ab?

Alle fünf gängigen Test-Typen lassen sich über Gherkin-Tags abbilden: Smoke (kurze Last für Verfügbarkeit), Load (erwartete Produktionslast), Stress (oberhalb erwarteter Last bis zum Bruch), Spike (plötzliche Last-Peaks) und Soak (Dauerlast über Stunden). Die Tag-Konfiguration (@vus, @stages, @duration) macht den Unterschied.

Was ist neu in k6 2.0 für BDD-Setups?

Drei Features sind besonders relevant: die neue Assertions-API mit expect()-Stil ersetzt verbose check()-Konstrukte, die native OpenTelemetry-Ausgabe vereinfacht Stakeholder-Dashboards, und der Subcommand-Mechanismus k6 x öffnet die Tür für KI-gestützte Test-Workflows (z.B. k6 x agent für Test-Generation). Quelle: Grafana Labs Release-Blog.

BDD-Beratung & Testautomatisierung

Sie wollen Behavior Driven Development mit Cucumber, Gherkin und Given-When-Then in Ihrem Team verankern? Unsere Experten begleiten von der Workshop-Einführung bis zur CI/CD-Integration.

BDD-Beratung anfragen

Finden Sie weitere interessante Artikel zum Thema: