Locust
Locust is an open-source, developer-friendly load testing framework that allows you to define user behavior in plain Python code. It's designed for testing web applications, APIs, and other systems, supporting hundreds of thousands of concurrent users through its event-based architecture. Locust offers a real-time web-based UI for monitoring and analysis, and is actively maintained with frequent updates (approximately every 62 days) [1, 2, 11, 19, 31]. It currently requires Python 3.10 or newer [31].
Warnings
- breaking The primary user classes `Locust` and `HttpLocust` were renamed to `User` and `HttpUser` respectively in version 2.0.0. Older scripts using `HttpLocust` will fail.
- deprecated The `min_wait`, `max_wait`, and `wait_function` attributes on `User` classes are deprecated. Use the `wait_time` attribute instead, which should be set to a function (like `between`, `constant`, `constant_throughput`) or a custom callable [27].
- gotcha When testing URLs with dynamic components (e.g., `/item?id=1`, `/item?id=2`), Locust will, by default, record each unique URL separately in statistics. This can lead to an explosion of metrics and make analysis difficult. To aggregate these, use the `name` parameter in your client request.
- gotcha The `TaskSet` class (an advanced feature for grouping tasks) does not automatically return control to its parent `User` or `TaskSet`. If not explicitly interrupted, a user entering a `TaskSet` will remain executing its tasks indefinitely.
- gotcha Locust has dependencies like `gevent` and `geventhttpclient` which are compiled from C code. This can lead to installation failures if the necessary build tools (e.g., C compiler, Python development headers) are not present on the system.
- gotcha By default, Locust looks for a test script named `locustfile.py`. If your script has a different name, or is not in the current directory, Locust will not find it.
- gotcha Only checking HTTP status codes (e.g., 200 OK) is often insufficient for validating successful user flows. A server might return 200 OK with an error message in the body, or simply not return the expected content.
Install
-
pip install locust
Imports
- HttpUser
from locust import HttpUser
- task
from locust import task
- between
from locust import between
- User
from locust import User
Quickstart
import os
from locust import HttpUser, task, between
class QuickstartUser(HttpUser):
wait_time = between(1, 2) # Users wait between 1 and 2 seconds after each task
host = os.environ.get('LOCUST_TARGET_HOST', 'http://localhost:8089') # Default host for testing
def on_start(self):
""" on_start is called when a Locust user starts running """
# Example: Simulating a login if required by the target system
# self.client.post("/login", json={"username":"test_user", "password":"test_password"})
print(f"Starting user on host: {self.host}")
@task
def hello_world(self):
self.client.get("/hello")
self.client.get("/world")
@task(3)
def view_items(self):
# Simulate viewing items with dynamic IDs, using 'name' to aggregate stats
for item_id in range(10):
self.client.get(f"/item?id={item_id}", name="/item")
def on_stop(self):
""" on_stop is called when a Locust user stops running """
# Example: Simulating a logout
# self.client.post("/logout")
print("Stopping user.")
# To run this, save as `locustfile.py` and execute `locust` from the terminal.
# Then open your browser to http://localhost:8089 to use the web UI.
# Alternatively, run headless: `locust -f locustfile.py --headless --users 10 --spawn-rate 5 -H http://your-target-host.com`