Home

Awesome

<div align="center">

Stress testing with Locust

</div>

Description

Locust is a distributed and scalable open-source library that helps you write effective load tests in pure Python. This repository demonstrates a modular architecture that can work as a template for quickly building a scalable stress testing pipeline with Locust.

Locust terminology

If you're unfamiliar with the terminologies and the general workflow of stress testing with Locust, then I recommend going through the official documentation first. With that out of the way, let's rehash a few terminologies that come up in this context quite often:

Task: In Locust, a Task is the smallest unit of a test suite. Usually, it means, any function or method that is decorated with the @task decorator.

TaskSet: A TaskSet is a class that establishes a contextual boundary between different groups of Tasks. You can essentially group multiple similar Tasks inside a TaskSet. Then you use the TaskSets from your User class.

User: In Locust, a User is a class that executes the tests either directly calling the Task methods or using TaskSets.

In more complex cases, the tests can further be organized by arranging them in multiple test modules. This template groups the Tasks using TaskSets and places multiple TaskSets in separate test modules to achieve better modularity.

Target API

Here, we're using Rapid API's currency exchange API to showcase the load testing procedure. The API converts one currency to another using the current exchange rate.

API anatomy

It takes three parameters in its query string:

1. q    : str - quantity
2. from : str - currency to convert from
3. to   : str - currency to convert to

And returns the converted value.

Access the API

Sign up for a Rapid API account and get your token. You can access the API via cURL like (You need to provide your API token in the header):

curl --request GET \
     --url 'https://currency-exchange.p.rapidapi.com/exchange?q=1.0&from=USD&to=BDT' \
     --header 'x-rapidapi-host: currency-exchange.p.rapidapi.com' \
     --header 'x-rapidapi-key: your-api-token'

The response will look like this:

84.91925⏎

Or, you might want to access it via Python. You can do so using the HTTPx library like this:

import httpx

url = "https://currency-exchange.p.rapidapi.com/exchange"

querystring = {"q": "1.0", "from": "USD", "to": "BDT"}

headers = {
    "x-rapidapi-host": "currency-exchange.p.rapidapi.com",
    "x-rapidapi-key": "your-api-token",
}

with httpx.Client(http2=True) as client:
    response = client.get(url, headers=headers, params=querystring)

print(response.text)

Stress testing pipeline

Below, you can see the core architecture of the load testing pipeline. For brevity's sake, files regarding containerization, deployment, and dependency management have been omitted.

src/
├── locustfiles         # Directory where the load test modules live
│   ├── __init__.py
│   ├── bdt_convert.py  # Load test module 1
│   └── rs_convert.py   # Load test module 2
├── __init__.py
├── auth.py             # Auth, login, logout, etc
├── locust.conf         # Locust configurations
├── locustfile.py       # Locust entrypoint
└── settings.py         # Read the environment variables here

The test suite has three primary components: setup.py, locustfiles, and the locust.conf file.

setup.py

The common elements required for testing, like auth, login, and logout functions reside in the setup.py file.

locustfiles

The load test modules reside in the locustfiles directory. Test modules import and use the functions in the setup.py file before executing each test.

In the locustfiles folder, currently, there are only two load test modules— bdt_convert.py and rs_convert.py. You can name your test modules whatever you want as long as the load testing classes and functions reside here.

locust.conf

The locust.conf file defines the configurations like hostname, number of workers, number of simulated users, spawn rate, etc.

Run the stress tests locally

Disclaimer

This dockerized application is production-ready. However, you shouldn't expose your environment file (.env) in production. Here, it was done only for demonstration purposes.