API Load Testing in Python with Locust

3519 VIEWS

Overview 

In this article, we will be going over what API load testing is, why API load testing is important, and how to carry out load tests on our API.

An increase in users of a product can put strain on the backend services of the product. This can result in two things:

  1. Your backend crashes because it cannot handle that much load, showing its unreliability
  2. Your backend handles the increase in load from the increase in users, showing it has been optimized to handle more load.

Given this analogy, there are multiple methods that we can use to make sure we don’t end up in option one. One of the most important methods is API Load Testing.

What is API Load Testing?

API load testing is the practice of checking if your API can handle a certain amount of load. It is the process by which we replicate multiple users sending requests to your API endpoints at once.

Why perform Load Tests on your API?

There are great insights that come with load testing our API, some of which will be highlighted below:

  1. It enables us to determine the load tolerance of our API.
  2. It helps to minimize performance risks.
  3. It also helps us determine the drawbacks of our API before pushing it to production.
Tools for performing API load tests

There are several tools that we could use for load testing our APIs. For example we have: Locust, JMeter, Grafana K6, LoadView, and many more. Our focus will be on Locust.

Locust is an open-source API load testing framework built with python. It supports running multiple load tests over a distributed system, therefore it can be used to simulate millions of users.

Locust also provides a nice graphical user interface for viewing data metrics about our API performance.

It has been tested with Battlelog (the web application for Battlefield games) to simulate multiple users carrying out different operations, so Locust has been proven to be reliable.

How to setup Locust for API Load Testing

For the sake of carrying out our load tests, we need to create the API that we will be load testing.

Our API will consist of 3 endpoints:

  • The first endpoint will return a simple “Hello World”
  • The second will return the cube root of numbers between 1, and 1000.
  • The last endpoint will return the square root of numbers between 1, 1000

To get started, we need to first install our dependencies, locust and flask. We can do this by using pip:

pip install locust flask

After our installation, we need to create our API endpoints. Create a new python file called main in your working directory, and add this piece of code:

from flask import 

Flask app = Flask(__name__) 


@app.route('/') 
def hello_world(): 
    return 'Hello World' 


@app.route('/cube-root/') 
def get_cube_root(): 
    new_list = [x**3 for x in range(0, 1001)] 
    return f'{new_list}' 

@app.route('/square-root/') 
def get_square_root(): 
    new_list = [x**2 for x in range(0, 1001)] 
    return f'{new_list}' 

if __name__ == '__main__':
    app.run()

Next, we run our development server like so:

python main.py

We can send requests to our endpoints to see our return values by opening the url in our browser like this: 

HELLO WORLD

SQUARE-ROOT

CUBE-ROOT

Next, we need to create our locust.py file which will hold the code for load testing our API. After creating our file, we need to add this piece of code:

from locust import HttpUser, task

class WebsiteUser(HttpUser): 
    
    @task 
    def hello_world(self): 
        self.client.get(url='/')

    @task 
    def square_numbers(self): 
        self.client.get(url='/square-root') 
    
    @task 
    def cube_numbers(self): 
        self.client.get(url='/cube-root')

This might look a bit confusing at first but we are going to understand each line, and what each block of code is meant to do.

At the top of our locust.py file, we first start by importing the basics like our HttpUser class followed by our task decorator.

Next, we create our WebsiteUser class that inherits the properties of our HttpUser class from the locust package.

The HttpUser class gives us the ability to create users which can send requests to any specified endpoint

Within our class, we need to define methods. These methods handle sending requests to the endpoint given. We can also create as many endpoints as we like with their respective request type, as shown below:

self.client.{method-type}(url=endpoint).

In the example above we specified two methods that handle sending GET requests to our API.

Finally, we can now run our locust file in our terminal like so:

locust -f locust.py

Once our locust script has started running, in our terminal we should an output similar to this:

[2022-06-27 17:31:33,960] 0x/WARNING/locust.main: System open file limit '1024' is below minimum setting '10000'. 
It's not high enough for load testing, and the OS didn't allow locust to increase it by itself.
See https://github.com/locustio/locust/wiki/Installation#increasing-maximum-number-of-open-files-limit for more info. 
[2022-06-27 17:31:33,960] 0x/INFO/locust.main: Starting web interface at http://0.0.0.0:8089 (accepting connections from all network interfaces) 
[2022-06-27 17:31:33,986] 0x/INFO/locust.main: Starting Locust 2.9.0

We can see a url pointing to our locust web interface. We would need to open that url in our browser like so:

In the locust web interface, we can define the number of users we want to simulate for our load tests, also we can set the spawn rate of each user, and finally the host—the URL API we want to load test.

Let’s fill in the form with the necessary information. For this load test we would want to simulate 50 users at the spawn rate of 2 users/second, and for the host, we would add our flask API URL. After filling in our information in the fields it should look like this: 

Finally, hit the Start Swarming button.

Next, we should see a screen with the tests running like so:

We can also view the charts of load tests by selecting the Charts option next to the Statistics option. These charts give insightful data on different areas of our API load tests.

TOTAL REQUESTS PER SECOND

This chart shows the total number of requests being sent to the endpoints per second.

RESPONSE TIMES

This chart shows the response time of all the endpoints.

NUMBER OF USERS

This chart shows how the users are being spawn in response to the set value of the spawn rate.

There are also ways to start our locust load testing server and get all this data in our terminal.

We can do this as follows:

locust -f locust.py --headless --users 50 --spawn-rate 2 -H http://localhost:5000

Conclusion

Thank you for sticking around till the end. We went over some of the important aspects of API load testing, and how we can perform load tests on our API using the python framework Locust. If you want to dive deeper into Locust, you can do so by going through their docs.


Somtochukwu is a backend engineer that loves explaining technical concepts as simply as he can through his articles.


Discussion

Click on a tab to select how you'd like to leave your comment

Leave a Comment

Your email address will not be published.

Menu
Skip to toolbar