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?
- k6 in 60 Sekunden
- BDD als gemeinsame Sprache
- k6-cucumber-steps: die Bridge
- Setup-Praxis: Gherkin-Feature zu k6-Skript
- Thresholds als Akzeptanzkriterien
- CI/CD-Pipeline mit GitHub Actions
- Reporting: BDD-Output und k6-Metriken konsolidieren
- Tool-Vergleich: k6, JMeter, Locust für BDD-Setups
- Fazit: 4 Fliegen mit einer Klappe
- FAQ: k6 + BDD + CI/CD
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.

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:
- API-Tests: Funktionalität jedes Endpunkts (Status-Codes, Response-Shape)
- Performance-Tests: Antwortzeiten unter Last (Smoke, Load, Stress, Spike, Soak)
- BDD-Lesbarkeit: Gherkin als gemeinsame Sprache für PO, Tester, Entwickler
- 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.
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:
npm install -g k6-cucumber-steps
npx k6-cucumber-steps init my-k6-bdd-project
Ein Feature-File mit Tags sieht dann so aus:
@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.

Die Step-Definitions sehen so aus:
// 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:
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.
// 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).

Hier das vollständige Workflow-YAML:
# .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:
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:
| Kriterium | k6 (2.0) | JMeter | Locust |
|---|---|---|---|
| BDD-Bridge verfügbar | k6-cucumber-steps (CLI) | Maven/Gradle-Plugins, schwergewichtig | locust-cucumber, weniger aktiv |
| Test-Sprache | JavaScript/TypeScript | XML + Groovy | Python |
| Cloud-Modus | Grafana Cloud k6 nativ | BlazeMeter, Octoperf, kostenpflichtig | Locust Cloud (Beta) |
| OpenTelemetry-Output | nativ in 2.0 | nur über Plugins | experimentell |
| GitHub Actions Integration | offizielle k6-Action | Custom-Workflow | Custom-Workflow |
| Lernkurve für BDD-Teams | flach (JS verbreitet) | steil (XML-Welt) | mittel |
| Reifegrad | 2.0 GA Mai 2026 | seit 2001 etabliert | seit 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

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.