Du willst eine Webanwendung oder API unter Last setzen, dein Team programmiert Python und du willst keine XML-Test-Pläne klicken? Dann ist Locust dein Werkzeug. Du schreibst Last-Szenarien in normalem Python, startest sie aus dem Terminal und siehst live im Web-UI, wie dein System reagiert.
In diesem Tutorial baust du Schritt für Schritt deinen ersten Locust-Lasttest. Installation, Locustfile-Aufbau, Web-UI vs. Headless-Mode, verteilte Worker und CI/CD-Integration. Am Ende vergleiche ich Locust mit JMeter und k6, damit du die richtige Wahl für deinen Stack triffst.
Aktuelle stabile Version: Locust 2.44.0 (Quelle: docs.locust.io). Empfohlene Python-Version: 3.12 oder neuer.
Inhaltsverzeichnis
- Was ist Locust?
- Locust installieren (pip, venv, Docker)
- Dein erstes Locustfile schreiben
- Locust starten: Web-UI und Headless-Mode
- Ergebnisse interpretieren
- Realistisches User-Verhalten modellieren
- Verteilte Last-Tests mit Master und Worker
- Locust in CI/CD-Pipelines (Jenkins + GitHub Actions)
- Locust vs. JMeter vs. k6
- Fünf typische Stolperfallen
- Fazit
- Häufige Fragen zu Locust (FAQ)
Was ist Locust?
Locust ist ein Open-Source-Lasttest-Werkzeug, das du in Python schreibst. Statt Test-Pläne in einer GUI zu klicken oder einer eigenen DSL zu lernen, definierst du User-Verhalten in echtem Python-Code, versionierst es im Repo wie jeden anderen Code und führst es lokal oder verteilt aus.
Unter der Haube nutzt Locust gevent für asynchrone IO. Das bedeutet: Ein einzelner Locust-Worker kann tausende virtuelle Nutzer simulieren, weil jeder „User" ein gevent-Greenlet ist und nicht ein eigener Thread. Das macht Locust deutlich speichersparender als JMeter, das pro virtuellem Nutzer einen Java-Thread öffnet.
Wenn du erst verstehen willst, wofür Lasttests gut sind und wie sie sich von Stress- oder Endurance-Tests unterscheiden, lies den Performance-Testing-Pillar. Für die vollständige Tool-Übersicht inklusive JMeter, k6 und Gatling siehe unseren Artikel Performance-Testing-Tools 2026 im Vergleich.
Locust installieren (pip, venv, Docker)
Locust läuft mit Python 3.12 oder neuer. Prüfe deine Version:
python3 --version
# erwarte: Python 3.12.x oder neuer
Best Practice: Locust in ein virtuelles Environment installieren, damit dein System-Python sauber bleibt:
python3 -m venv .venv
source .venv/bin/activate
pip install locust
locust --version
# erwarte: locust 2.44.0
Alternative ohne Python-Setup: Docker-Image vom offiziellen Maintainer:
docker run --rm -v $(pwd):/mnt/locust \
-p 8089:8089 \
locustio/locust:2.44.0 \
-f /mnt/locust/locustfile.py
Mit Docker bleibst du unabhängig vom lokalen Python-Setup. Genau das brauchst du, wenn Locust später in einer CI/CD-Pipeline läuft (siehe Abschnitt weiter unten).
Dein erstes Locustfile schreiben
Locust erwartet eine Datei namens locustfile.py. Inhalt für deinen ersten Test:
from locust import HttpUser, task, between
class WebsiteUser(HttpUser):
wait_time = between(1, 3) # 1 bis 3 Sekunden Pause zwischen Tasks
@task
def index(self):
self.client.get("/")
@task(3) # diese Task läuft 3-mal so oft wie index
def about(self):
self.client.get("/about")
Was passiert hier:
HttpUserist die Basis-Klasse für HTTP-basierte Last-Tests. Jeder virtuelle Nutzer ist eine Instanz dieser Klasse.wait_time = between(1, 3)simuliert eine Pause zwischen den Requests. Realistisch, weil echte Nutzer nicht im Sekundentakt klicken.@taskmarkiert eine Methode als Test-Aktion. Das Gewicht in Klammern (hier 3) bestimmt die relative Häufigkeit.self.clientist ein vorkonfigurierter HTTP-Client (basiert aufrequests), der Cookies und Sessions per User-Instanz verwaltet.
Locust starten: Web-UI und Headless-Mode
Im Locustfile-Verzeichnis startest du Locust mit:
locust -f locustfile.py --host=https://example.com
Locust öffnet einen Web-Server auf http://localhost:8089. Im UI gibst du an, wie viele Nutzer du simulieren willst, mit welcher Spawn-Rate (Nutzer pro Sekunde) und über welche Dauer. Live siehst du Requests pro Sekunde, Response Times und Fehler.
Für CI/CD oder reproduzierbare Runs nutzt du den Headless-Mode. Kein UI, alle Parameter via CLI:
locust -f locustfile.py \
--host=https://example.com \
--headless \
--users 100 \
--spawn-rate 10 \
--run-time 5m \
--html report.html \
--csv results
Was passiert hier:
--headless: Kein Browser-UI, läuft autonom durch.--users 100: 100 gleichzeitige virtuelle Nutzer als Ziel.--spawn-rate 10: 10 neue Nutzer pro Sekunde, bis 100 erreicht sind.--run-time 5m: Test läuft 5 Minuten, dann automatisch Stopp.--html report.html: HTML-Report nach Ende, ablegbar als CI-Artefakt.--csv results: CSV-Output für nachträgliche Auswertung (Trends über Builds).
Ergebnisse interpretieren
Nach dem Lauf hast du im Web-UI oder im HTML-Report folgende Metriken pro Endpunkt:
| Metrik | Bedeutung | Worauf du achtest |
|---|---|---|
| # Requests | Anzahl ausgeführter Requests | Muss zur Erwartung passen (RPS × Laufzeit) |
| # Failures | Fehlerhafte Requests (Timeout, 4xx, 5xx) | Unter 1 % bei realistischer Last |
| Median Response Time | 50. Perzentil | Schneller Sanity-Check |
| 90% / 95% / 99% | Tail-Latenzen | Industrie-Standard für SLAs ist meist 95th Percentile |
| Average / Min / Max | Mittel, Minimum, Maximum | Max zeigt Worst-Case, Average ist anfällig für Ausreißer |
| Current RPS | Aktuelle Requests pro Sekunde | Tatsächlicher Durchsatz unter dieser Last |
Wichtig: Wenn die Spawn-Rate höher ist als das System verarbeiten kann, baut sich eine Warteschlange auf. Response Times steigen dann nicht wegen schlechter Code-Performance, sondern wegen Backpressure. Im UI siehst du das daran, dass die Failure-Rate sprunghaft ansteigt sobald du eine bestimmte User-Zahl überschreitest.
Realistisches User-Verhalten modellieren
Echte Nutzer machen mehr als eine Seite aufrufen. Sie loggen sich ein, navigieren durch Flows und halten Sessions am Leben. So bildest du das in Locust ab:
from locust import HttpUser, task, between
class CustomerUser(HttpUser):
wait_time = between(2, 5)
def on_start(self):
# einmal pro virtuellem User beim Start: Login
self.client.post("/login", json={
"user": "demo",
"password": "secret123",
})
@task(5)
def view_products(self):
self.client.get("/products")
@task(2)
def view_product_detail(self):
self.client.get("/products/42")
@task(1)
def add_to_cart(self):
self.client.post("/cart", json={"product_id": 42, "quantity": 1})
on_start läuft einmal pro virtuellem User vor dem ersten Task. Ideal für Login, Token-Holen oder Datenvorbereitung. on_stop würde analog beim Beenden laufen (Logout, Cleanup).
Die Gewichte 5/2/1 ergeben eine 5:2:1-Verteilung. Wenn 80 Aktionen pro Minute laufen, sind das etwa 50 Product-Listings, 20 Detail-Views und 10 Cart-Adds. Realistischer als gleichverteilte Tasks.
Verteilte Last-Tests mit Master und Worker
Eine einzelne Locust-Instanz schafft 1.000 bis 5.000 virtuelle User auf einer Standard-Workstation. Mehr brauchst du verteiltes Setup: ein Master, mehrere Worker. Der Master koordiniert, die Worker generieren Last.
# Terminal 1: Master starten
locust -f locustfile.py --master
# Terminal 2 und 3: Worker starten
locust -f locustfile.py --worker --master-host=127.0.0.1
locust -f locustfile.py --worker --master-host=127.0.0.1
Im Web-UI wählt der Master die User-Zahl, verteilt sie auf die Worker. Mit Docker-Compose hast du das in einer Datei:
version: '3'
services:
master:
image: locustio/locust:2.44.0
ports: ["8089:8089"]
volumes: ["./:/mnt/locust"]
command: -f /mnt/locust/locustfile.py --master --host=https://example.com
worker:
image: locustio/locust:2.44.0
volumes: ["./:/mnt/locust"]
command: -f /mnt/locust/locustfile.py --worker --master-host=master
deploy:
replicas: 4
Vier Worker auf einem Host, der Master orchestriert. Skalierbar auf Kubernetes wenn der Bedarf wächst.
Locust in CI/CD-Pipelines (Jenkins + GitHub Actions)
Performance-Tests gehören in die Pipeline. Ein Lasttest, der nur manuell läuft, fällt regelmäßig hinten runter. Qualität ist kein Gate am Ende der Pipeline. Qualität ist die Pipeline.
Jenkinsfile (declarative pipeline) für einen nächtlichen Locust-Lauf gegen Staging:
pipeline {
agent any
triggers { cron('H 3 * * 1-5') }
stages {
stage('Locust Load Test') {
steps {
sh '''
docker run --rm -v $WORKSPACE:/mnt/locust \\
locustio/locust:2.44.0 \\
-f /mnt/locust/locustfile.py \\
--host=https://staging.example.com \\
--headless --users 200 --spawn-rate 20 --run-time 10m \\
--html /mnt/locust/report.html --csv /mnt/locust/results
'''
}
}
stage('Publish Report') {
steps {
publishHTML([reportDir: '.', reportFiles: 'report.html',
reportName: 'Locust Report'])
archiveArtifacts artifacts: 'results_*.csv'
}
}
}
post {
failure { slackSend channel: '#perf-tests', message: "Locust-Run fehlgeschlagen: ${env.BUILD_URL}" }
}
}
GitHub Actions Workflow als Alternative:
name: locust-nightly
on:
schedule:
- cron: '0 3 * * 1-5'
jobs:
loadtest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Locust
run: |
docker run --rm -v ${{ github.workspace }}:/mnt/locust \\
locustio/locust:2.44.0 \\
-f /mnt/locust/locustfile.py \\
--host=https://staging.example.com \\
--headless --users 200 --spawn-rate 20 --run-time 10m \\
--html /mnt/locust/report.html --csv /mnt/locust/results
- uses: actions/upload-artifact@v4
with:
name: locust-report
path: |
report.html
results_*.csv
Für tieferes Jenkins-Setup siehe Jenkins für Continuous Integration und Continuous Deployment. Für ein größeres CI/CD-Bild siehe CI/CD-Pipeline-Grundlagen.
Locust vs. JMeter vs. k6
Welches Tool zu dir passt, hängt von Team und Stack ab. Drei Open-Source-Alternativen im direkten Vergleich:
| Kriterium | Locust | JMeter | k6 |
|---|---|---|---|
| Sprache | Python | GUI / XML | JavaScript |
| Codefreie GUI | ❌ | ✅ | ❌ |
| Async-Modell | gevent-Greenlets | Java-Threads | Goroutines |
| Speicherbedarf pro User | Sehr niedrig | Hoch | Sehr niedrig |
| Live-Reporting im UI | ✅ (Web-UI) | ❌ (Listener notwendig) | ❌ (Grafana extern) |
| Verteilte Last | Master/Worker | Distributed Mode | k6 Cloud, Kubernetes |
| Sweet Spot | Python-Teams, schnelles Skripting | Mixed Protocols, GUI-Einsteiger | DevOps-Teams, API-Tests |
Faustregel: Locust wenn dein Team Python schreibt und du schnell Code-basierte Lasttests brauchst. JMeter wenn du Mixed Protocols (HTTP, JDBC, JMS, Kafka) testen willst oder eine codefreie GUI ein Onboarding-Vorteil ist (siehe JMeter Tutorial). k6 für moderne DevOps-Teams mit JavaScript-Affinität und Grafana-Stack (siehe k6 Performance Testing Praxis). Wer eine Schwester-Praxis-Sicht auf klassisches JMeter sucht, findet sie im JMeter-Lasttest-Artikel.
Fünf typische Stolperfallen
- Headless ohne
--htmloder--csv. Du läufst Locust in der Pipeline, alle Ergebnisse landen in der Console. Beim nächsten Build-Klick alles weg. Immer mindestens ein Output-Flag setzen, sonst nichts archivierbar. - Zu wenig Spawn-Rate. Wenn du 1.000 User mit einer Spawn-Rate von 1 startest, brauchst du 1.000 Sekunden bis alle aktiv sind. Realistische Last erst gegen Ende. Faustregel: Spawn-Rate so wählen, dass die Ramp-up-Phase 30 bis 60 Sekunden dauert.
- Connection Reuse vergessen. Locust nutzt
requests-Sessions per virtuellem User. Wenn du inon_starteinen Session-Token holst, ist er für alle Tasks dieses Users verfügbar. Wenn du ihn pro Task neu holst, misst du nur dein Login-Endpoint. - gevent-Limits unterschätzt. Ein Locust-Worker schafft 1.000 bis 5.000 User. Mehr braucht verteiltes Setup. Wer 10.000 User auf einem Worker forciert, sieht steigende CPU-Last und sinkende Genauigkeit.
- Wait-Time falsch verstanden.
between(1, 3)ist die Pause zwischen Tasks, nicht zwischen Requests innerhalb eines Tasks. Wer eine konstante Last über Zeit braucht, nutztconstant_throughput()stattbetween().
Fazit
Locust ist die richtige Wahl, wenn dein Team Python schreibt und Lasttests im Repo statt in einer GUI lebt. Version 2.44 läuft stabil mit Python 3.12, der gevent-Kern macht tausende User auf einer Workstation möglich, das Web-UI gibt dir Live-Feedback während du tunst.
Tests sind kein Add-on. Tests sind der Vertrag. Wenn du Lasttests in die Pipeline bringst, hörst du auf zu raten und fängst an zu messen. Das gilt für Locust, das gilt für JMeter, das gilt für k6.
Wenn du Locust mit einem klassischen JMeter-Setup vergleichen willst, lies das JMeter Tutorial als direkte Schwester. Für das große Bild Performance-Testing-Strategie siehe den Performance-Testing-Pillar.
Häufige Fragen zu Locust (FAQ)
Ist Locust kostenlos?
Ja. Locust steht unter der MIT-Lizenz und ist vollständig Open Source. Keine kommerziellen Lizenzkosten für Entwicklung, CI/CD oder verteilte Worker. Der Source-Code liegt auf GitHub unter locustio/locust.
Welche Python-Version brauche ich für Locust 2.44?
Empfohlen ist Python 3.12 oder neuer. Ältere Versionen funktionieren oft noch, sind aber nicht offiziell getestet. Bei Neuinstallationen direkt Python 3.12 oder 3.13 nutzen.
Wie viele virtuelle Nutzer schafft Locust auf einem Laptop?
Realistisch 1.000 bis 5.000 User auf einer Standard-Workstation mit 16 GB RAM, abhängig von der Komplexität deines Locustfiles. Für mehr Last verteiltes Setup mit Master und Worker, oder eine Cloud-Plattform wie unsere eigene QLoad-Lösung.
Locust oder JMeter: was nehme ich für eine neue Lasttest-Pipeline?
Für Python-Teams und Code-getriebene Tests ist Locust die natürliche Wahl. Für gemischte Protokoll-Tests (HTTP plus JDBC plus Kafka) und Teams ohne Code-Affinität bleibt JMeter robuster. Vergleichstabelle siehe Performance-Testing-Tools 2026.
Wie integriere ich Locust in Jenkins?
Am saubersten via Docker-Image locustio/locust:2.44.0, das du in einem Stage ausführst und HTML-Report sowie CSV-Output als Artefakt publishst. Bei dauerhaftem Setup lohnt sich ein Performance-Plugin, das Response-Time-Trends über Builds visualisiert. Mehr Details im Jenkins-CI/CD-Artikel.
Was ist der Unterschied zwischen between() und constant_throughput()?
between(1, 3) wartet zwischen 1 und 3 Sekunden zwischen Tasks (variable Last, realistisches Klick-Verhalten). constant_throughput(0.5) erzwingt 0,5 Tasks pro Sekunde pro User (konstanter Durchsatz, gut für SLA-Tests). Wer einen festen RPS-Wert messen will, nutzt constant_throughput().
Kann ich Locust für gRPC- oder WebSocket-Tests nutzen?
Ja. Locust hat eine pluggable Client-Architektur. FastHttpUser ist schneller als HttpUser für reine HTTP-Tests. Für gRPC nutzt du das locust-grpc-Package, für WebSocket locust-plugins. Beide sind aktiv gepflegte Community-Pakete.