By using this web site you accept our use of cookies. More information about cookies
Accept
Infopulse - Expert Software Engineering, Infrastructure Management Services
By using this web site you accept our use of cookies. More information about cookies
Accept
Infopulse - Expert Software Engineering, Infrastructure Management Services
Infopulse - Expert Software Engineering, Infrastructure Management Services
reCAPTCHA
Send message Please fill in this quick form and we will send you a free quote shortly.
* Required fields
Your privacy is important to us. We will never share your data.
Subscribe to our updates Be among the first to get exclusive content on IT insights, innovations, and best practices.
* Required fields
Your privacy is important to us. We will never share your data.
Subscribe to our New career opportunities Please fill in this quick form to be among the first to receive our updates.
* Required fields
Your privacy is important to us. We will never share your data.
Subscribe to our updates Be among the first to get exclusive content on IT insights, innovations, and best practices.
* Required fields
Your privacy is important to us. We will never share your data.
Photo of Oleksii Ostapov Send an email to Oleksii Ostapov Please fill in this quick form to contact our expert directly.
* Required fields
Your privacy is important to us. We will never share your data.
Infopulse - Expert Software Engineering, Infrastructure Management Services
Read the Full Case Study Don't miss the most interesting part of the story!
Submit this quick form to see the rest and to freely access all case studies on our website.
* Required fields
Your privacy is important to us. We will never share your data.

Performance Testing with Locust [Part 3]

This is the final article about the performance testing tool Locust. Today, I’ll share my findings accumulated in the process of work.

Previous articles:

Authorization

When writing the first tests with Locust, I faced the need to get an authorization token on one server and then use it on the second one for performance testing. Here immediately arose the question — of how to do it, because the instrument is tuned to send all the requests to one resource, which we define in the console starting the test. There are several variants to solve the problem:

  • to disable authorization on the tested resource — if there is such a possibility;
  • to generate a token in advance and insert it into the text code before launch; it’s the worst variant, which demands manual work at each launch, but has the right to exist in several rare cases;
  • to send a request using library requests and receive a token in the response — luckily, the syntax is similar.

I have chosen the third variant. An example from the first article, which describes different possibilities of obtaining a token, is given below. The authorization server is google.com and, since there is no token, I will receive the simplest values:

from locust import HttpLocust, TaskSet, task
import requests

class UserBehavior(TaskSet):
  def on_start(self):
      response = requests.post("http://mysite.sample.com/login", {"username": "ellen_key", "password": "education"})
      # get "token" from response header
      self.client.headers.update({'Authorization': response.headers.get('Date')})
      # get "token" from response cookies
      self.client.cookies.set('Authorization', response.cookies.get('NID'))
      # get "token" from response body
      self.client.headers.update({'Authorization': str(response.content.decode().find('google'))})

As it’s clear from the example, before a work task begins, a user sends a request to an external server and processes an answer, placing the data to headers or cookies.

Headers

When working on the request headers, it is necessary to take into account several important details. For each particular request, it is possible to set its own headers in the following way:

self.client.post(url='/posts', data='hello world', headers={'hello': 'world'})

Running the mentioned example, the hello header key will be added to already existing headers of a client’s session, but in this request only — in all subsequent requests it will be absent. To make the header permanent, you can add it into a session:

One more interesting finding is that if we mention a header, which already exists in the session in a request, it will be rewritten, but only for this request. So, don’t be afraid of erasing something important.

But there are some exceptions. If we need to send a multipart form, the request will automatically form a header Content-Type, where a form data divider will be indicated. But if we forcibly re-write the header with the headers argument, then the request will crush, because the form will not be able to be processed correctly.

Also, it is worth drawing attention to the fact that all the headers are strings in all cases. Trying to submit an integer, for example {‘aaa’: 123} the request will not be sent and the code will return exception InvalidHeader.

Distributed testing

For distributed testing, locust gives several CLI arguments: –master and –slave, for strict roles determination. With this, the machine with master will not simulate loading, but only gather statistics and coordinate the work. Let’s try to launch test server and several sessions in distributed mode executing commands in different consoles:

json-server --watch sample_server/db.json
locust -f locust_files\locust_file.py --master --host=http://localhost:3000
locust -f locust_files\locust_file.py --slave --master-host=localhost
locust -f locust_files\locust_file.py --slave --master-host=localhost

Opening the locust in a browser ( ), you can see that in the right upper corner we have the number of machines that will perform the loading.

Performance Testing with Locust [Part 3] - Infopulse -1

Testing without UI

When all the tests are written and debugged, it is a good idea to include them in the regress automatic testing and simply periodically check results. With the following command, you can launch the locust test without UI:

locust -f locust_files\locust_file.py --host=http://localhost:3000 --no-web -c 10 -r 2 --run-time 1m --csv=test_result

where

  • –no-web — is an argument allowing to launch tests without UI
  • -c 10 — maximum number of users
  • -r 2 — users increase per second
  • –run-time 1m — test execution time (1 minute)
  • –csv=test_result — after the test execution in the current folder 2 csv files with results will be created and their names will begin with test_result.

Final facts, findings, and conclusions

Distributed testing can be combined with regression testing — to guarantee that all the nodes for loading are started, you can add the argument –expect-slaves=2 on the master’s; in this case the test will begin only when at least 2 nodes are launched.

Several times, I have faced the situation when the tested resource worked with HTTPS only; at the same, time the certificate was generated by a customer and an operating system marked it as suspicious. To make tests work successfully it is possible to add an argument ignoring the safety check to all the requests, for instance:

self.client.get("/posts", verify=False)

To hide multiple warnings about unsecure connection just add next lines in the locustfile start lines:

import urllib3
urllib3.disable_warnings()

Because I am not always sure in what environment the tests will be launched, I always mention this argument/moment.

That is all I wanted to share regarding performance testing with Locust, a simple and convenient tool with wide capabilities for testing and variability for creating requests and processing answers of the server. Thank you for reading it to the end.