Skip to content
All posts
APITestingPython

Rest API Stress Testing with Locust Python

January 12, 2021·Read on Medium·

As a developer, you are probably doing so many types of tests (probably not 😅) into your code like Unit Testing, UI tests, and more. Most of the time, stress testing is ignored in a sprint or release process. After all, if the system is working under functional testing, it’s good to go, right? ️

Website vector created by stories
Load testing is a type of performance test that checks how systems function under a heavy number of concurrent virtual users performing transactions over a certain period of time.

Why? When it comes to high traffic, most applications become slow. When it slows down, customers tend to lose interest if it is performing poorly with crashes or delayed load time. Time is money, isn’t it?

Street testing with locust.io

Here is where Locust.io comes to the rescue. Locust is Open-source Python-based load testing. All you need is to write a script using the locust library. It’s very simple and easy-to-use which for me as a Python beginner is easier to understand.

So Why Locust?

  • Define user behaviour in code
  • No Cluttered UI. Just a plain code structure
  • Clean load testing tool unlike JMeter
  • Distributed and Scalable load testing
  • VCS and Resource friendly
  • Easier for beginners who don’t know python

Here is the sample code of a simple locust setup

Setup Environment

Let do the python installation.

MacOS — http://bit.ly/2XtUdae

Windows — http://bit.ly/2LD55zQ

Linux — http://bit.ly/3nCMAbW

These guides go over the proper installation of Python for development purposes, as well as setuptools, pip, and virtualenv.

I would recommend using PyCharm Jetbrain. It already has a built-in virtual environment for each project.

Installing Virtual Environment

python3 -m pip install virtualenv

Every time you create a Python project, run the following command

python3 -m venv venv

A venv folder will be created. Now, to activate virtual env, run the following command

source venv/bin/activate

And it should show (venv) at the first command indicating you are already in the virtual environment

(venv) ➜  Locust git:(master)

Installation

Let’s start with creating a project folder named locust-project.

mkdir locust-project
cd locust-project

Now activate the virtual environment

python3 -m venv venv
source venv/bin/activate

Install Locust

pip3 install locust && locust -V

If something is not right or an error occurred, please refer to the locust wiki or Google the error keyword. It works every time.

Create Load Test Script

Now, create the main file called locustfile.py in the locust-project.

Import locust library

from locust import HttpUser, between, task

Write a class that extends the HttpUser class. Can be a name based on your preference.

class ApiUser(HttpUser):
wait_time = between(2, 5)

The behaviour of a simulated user is represented by a class in your locust file. When you start a test run, Locust will create an instance of the ApiUser class for each concurrent user.

The wait_time method is an optional feature used to make a simulated real user wait a specified time between task executions. between(2,5) indicates that Locust will wait 2–5 seconds before proceeding with each task.

Now, create several tasks based on your preferences. For example, using the API to get the profile and todo list.

@task(1)
def profile(self):
self.client.get('/profile') @task(5)
def get_todo_list(self):
self.client.get('/todo')

Methods decorated with @task are the core of your locust file. For every running user, Locust creates a greenlet micro-thread, that will call those methods. Tasks are picked at random, but you can give them different weights. The above configuration will make Locust users 5x likelier to pick get_todo_list than profile. By default, it will equally call between the tasks.

How about user login?

Locust provides on_start and on_stop functions. A user will call its on_start method when it starts running, and its on_stop method when it stops running. Usually, the login part is the first checkpoint before using other endpoints.

def on_start(self):
self.client.post("/login", {
"username":"admin",
"password":"admin1234"
}) def on_stop(self):
logging.info("On Stop Triggered")

And finally, the code would be something like this

from locust import HttpUser, between, task
class ApiUser(HttpUser):
wait_time = between(2, 5) def on_start(self):
self.client.post("/login", {
"username":"admin",
"password":"admin1234"
}) @task(1)
def profile(self):
self.client.get('/profile') @task(5)
def get_todo_list(self):
self.client.get('/todo') def on_stop(self):
logging.info("On Stop Triggered")

In Locust, you can separate the task into another class. Let’s create a class MyTasks on top of ApiUser

class MyTasks(TaskSet):
@task(1)
def profile(self):
self.client.get('/profile') @task(5)
def get_todo_list(self):
self.client.get('/todo')

class ApiUser(HttpUser):
wait_time = between(2, 5) def on_start(self):
self.client.post("/login", {
"username":"admin",
"password":"admin1234"
}) tasks = {MyTasks}

Finally, Let’s Stress It

Let’s test it by running the below command

Running Locust in Local

locust

Note that if you are using something other than locustfile.py, you need to put -f filename.py

locust -f filename.py

You will see something like this in your terminal

[2021-01-12 13:12:27,155] Kapalbiru88.local/INFO/locust.main: Starting web interface at http://0.0.0.0:8089 (accepting connections from all network interfaces)
[2021-01-12 13:12:27,164] Kapalbiru88.local/INFO/locust.main: Starting Locust 1.4.1

Your code will be able to run and you should see the below interface if you open up the browser with the http://localhost:8089 . Fill up the configuration below and start swarming!

All you need is to fill the input fields with anything based on your preferences

Number of total user — How many users you want to simulate

Spawn rate — How many users will be spawned every second until the total number of users is reached

Host — What is your targeted endpoint

Once you start, you will notice that the page redirects to a different interface, similar to the one below

This screenshot is based on my load testing

You can see statistics for every endpoint, total requests, media response, response percentile, and RPS. Locust also provides graphs with the statistic of the total request per second, response time, and the increment of the number of users.

Extras

Web Authenticate

If you want to restrict access from an unknown user, you can use --web-auth=username:password in the locust argument.

# locust --web-auth=admin:admin

Running Locust distributed

Once a single machine isn’t enough to simulate the number of users that you need, Locust supports running load tests distributed across multiple machines.

# locust --master --master-bind-port=1234 --master-bind-host=X.X.X.X 

The master command is only for a web interface. Even you start swarming, it won’t work because the slave is not running yet. Let’s say we run 4 workers:

# locust --worker --master-host=X.X.X.X --master-port=1234 &
locust --worker --master-host=X.X.X.X --master-port=1234 &
locust --worker --master-host=X.X.X.X --master-port=1234 &
locust --worker --master-host=X.X.X.X --master-port=1234

It’s recommended that you start a number of simulated users that are greater than number of user classes * number of workers when running Locust distributed.

Conclusion

I found Locust to be amazing, easy to use, and supportive of REST API testing out of the box. This tutorial is just the tip of the iceberg. Find out more from the references below.

So that’s it. If you found this useful, do share with your friends or colleagues. Thanks for your time!

References:

https://docs.locust.io/en/stable/what-is-locust.html

https://blog.gojekengineering.com/a-guide-to-load-testing-via-locust-8539e7987b73

More content at plainenglish.io

Found this helpful?

If this article saved you time or solved a problem, consider supporting — it helps keep the writing going.

Originally published on Medium.

View on Medium
Rest API Stress Testing with Locust Python — Hafiq Iqmal — Hafiq Iqmal