Introducing Locust: a Python Load Testing Tool
As a developer, there are many tools that we can use to test the load performance of our websites or web services. Personally, I think Locust is one of the best load testing tools. It is one of the most developer-friendly tools as it is scriptable and easy to modify even when using basic python syntax. This article will show you a simple introduction to Locust.
Features
In their website documentation, you might click here, Locust claims to have some features:
- Write test scenarios in plain old Python
- Distributed and scalable — supports hundreds of thousands of concurrent users
- Web-based UI
- Can test any system
- Hackable
If we run Locust, the web interface will show 6 pages: 1) Statistics, to know the request number and its status. 2) Charts, to know the data as graphic. 3) Failures, to know the fail requests. 4) Exceptions, to know exceptions of the failures. 5) Tasks, to know ratio per user of our scenarios. 6) Download Data, to download all information of requests in csv format.
How to use it?
This article will show you how to use locust, starts from installation to its simple usage.
Preparation
To guide you to this tool, I had prepared an application service containing performance testing sample and attachment for its installation steps. Click here to Download. You also need to make sure that Python 3.6x or later have already installed in your computer.
Installation
To install Locust, write the command bellow:
pip install locust
After you finish installing Locust, you can check the Locust version and packages that auto installed in your computer like this:
locust -V
pip list
Sample Script Code
Now, you can start using Locust as your testing tool. First of all, create file named “locustfile.py” or other. Write the simple script code bellow. Remember that the script was designed for the application sample that I have prepared before. Link to Download.
You can run the script by typing this command:
locust
or add “ — web-port” attribute to run the script in different port, as follows:
locust --web-port=8080
After Locust is running, you can access the default url at http://localhost:8089 to see its interface. By default, you can set the host, number of user, and spawn rate.
Explanation
These are the explanations of the simple script code above:
- Import Locust package that you want to use.
from locust import HttpUser, task, between, tag
from locust import events
2. Write the following code if you want to add messages when the test is starting:
@events.test_start.add_listener
def on_test_start(environment, **kwargs):
print("A new test is starting")
3. Write the following code if you want to add messages when the test is ending:
@events.test_stop.add_listener
def on_test_stop(environment, **kwargs):
print("A new test is ending")
4. The code bellow shows the class that will be detected as a testing scenario. You can add other scenarios by adding new classes and make them subclasses of HttpUser class.
class MyApp(HttpUser):
5. This code shows a task or a part of scenario that will be running. You can change the method from post to others like get, put, or delete.
def create_data(self):
self.client.post("/", json={"firstname": "Magnus", "lastname": "Calsen"})
6. Tag decorator is used to differentiate tasks that will be executed during the test.
@tag("create_data")
- To run the test which is filtered by the tag decorator, you can write this command:
format: --tags {tag1} {tag2} ... {tagx}e.g.
locust --tags create_data update_data
- You can also keep running the test by excepting certain tasks. Write this command:
format: --exclude-tags {tag1} {tag2} ... {tagx}e.g.
locust --exclude-tags create_data update_data
7. To make a priority order of the tasks, you can add a numeric parameter to the tag decorator:
@task(2)
8. To give validation of the task, you can write this code:
with self.client.put("/{id}".format(id=1), json={"firstname": "Magnus", "lastname": "Calsen"}) as response:
try:
if response.json().get("firstname") != "Magnus":
response.failure("Did not get expected value in firstname")
except JSONDecodeError:
response.failure("Response could not be decoded as JSON")
except KeyError:
response.failure("Response did not contain expected key 'firstname'")
9. To set the waiting time for simulated users, we can add wait time variable. Locust provides us some wait_time attribute, such as constant, between, constant_throughput, and constant_pacing. For detail information you can check the documentations.
wait_time = between(3, 5)
Conclusions
Locust is a good tool to make performance testing for our website or web services. It is developer friendly and have a good interface. As mention in the documentation, this tool has many other features, such as running without web interface, docker integration, and others.