📜 ⬆️ ⬇️

Load testing with locust. Part 3

The final article about the tool for load testing Locust. Today I will share the observations that have accumulated in the process. As always, the video is attached.

Part 1 - Testing with Locust
Part 2 - Advanced Scenarios


Authorization


When writing my first tests with Locust, I was faced with the need to log in on one resource, having received an authorization token, which I would later use in load testing. Then the question immediately arose - how to do it, because the tool is sharpened to send all requests to one resource, which we specify in the console when the test is run. There are several solutions to the problem:
')

I chose the third option. Below I propose a converted example from the first article with different possibilities of obtaining a token. As the authorization server will google.com and, so
as there is no token, I will get 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 you can see from the example, before starting work, the user sends a request to a third-party server and processes the response, placing the data in headers or cookies.

Headers


When working with request headers, there are several important points to consider.
For each separate request, you can specify your own set of headers as follows

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

When executing this example, the hello header will be added to the already existing client session headers, but only in this query - it won't be in all the following ones. To make the title permanent, you can add it to the session:

 self.client.headers.update({'aaa': 'bbb'}) 

Another interesting observation is that if we specify in the request a header that is already in the session, it will be overwritten, but only to this request. So you can not be afraid to accidentally wipe something important.

But there are exceptions. If we need to send a multipart form, the request will automatically form a Content-Type header, in which the form data separator will be specified. If we forcefully rewrite the header with the help of the headers argument, then the request will fail, since the form cannot be correctly processed.

It is also worth noting that all headers are required strings. If you try to specify a number, for example {'aaa': 123} , the request will not be sent and the code will throw an InvalidHeader exception

Distributed testing


For distributed testing, locust provides several CLI arguments: --master and --slave , for clearly defining roles. At the same time the machine with the master will not simulate the load, but only collect statistics and coordinate the work. Let's try to start our test server and several sessions in distributed mode by 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 


Open the locust in the browser ( localhost: 8089 ), you can note that in the upper right corner we have the number of machines that will carry out the load



Testing without UI


When all the tests are written and debugged, it would be nice to include them in the regression automated testing and simply check the results periodically. With the following command, you can run 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


Final facts, observations and conclusions


Distributed testing can be combined with regression testing - in order to ensure that all the nodes for the load have started, you can add the argument --expect-slaves = 2 on the master, in which case the test will start only when at least 2 nodes are started.

I faced a situation a couple of times - the tested resource works only on HTTPS, while the certificate was generated by the customer and the operating system marks it as suspicious. For the tests to work successfully, you can add an argument to all requests that ignores the security check, for example:

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

Since I can not always be sure in which environment the tests will be run, I always specify this argument.

That's all what I wanted to share. For myself, I discovered a simple and convenient tool with great testing capabilities and variations in creating requests and processing server responses. Thank you for reading to the end.

Source: https://habr.com/ru/post/433304/


All Articles