Skip to main content

Writing a cortisolfile

Writing a cortisolfile

Cortisol has been inspired by Locust on defining the behaviour of users.

In fact, there is only one difference between a cortisol file and a locust file. The user defined class in the cortisol file must extend the CortisolHttpUser. The rest is exactly the same.

Let's look at a realistic example that is slightly modified from the original Locust example.

    import time
from cortisol.cortisollib.users import CortisolHttpUser
from locust import task, between

class QuickstartUser(CortisolHttpUser):
wait_time = between(1, 5)

@task
def hello_world(self):
self.client.get("/hello")
self.client.get("/world")

@task(3)
def view_items(self):
for item_id in range(10):
self.client.get(f"/item?id={item_id}", name="/item")
time.sleep(1)

def on_start(self):
self.client.post("/login", json={"username":"foo", "password":"bar"})

Let's break it down

    import time
from cortisol.cortisollib.users import CortisolHttpUser
from locust import task, between

A cortisol file is just a normal Python module, it can import code from other files or packages.

    class QuickstartUser(CortisolHttpUser):

Here we define a class for the users that we will be simulating. It inherits from CortisolHttpUser <cortisollib.users.CortisolHttpUser> which gives each user a client attribute, which is an instance of HttpSession <locust.clients.HttpSession> behind the scenes, that can be used to make HTTP requests to the target system that we want to load test. When a test starts, locust will create an instance of this class for every user that it simulates, and each of these users will start running within their own green gevent thread.

For a file to be a valid cortisolfile it must contain at least one class inheriting from :py:class:CortisolHttpUser <cortisollib.users.CortisolHttpUser>.

Behind the scenes, the class CortisolHttpUser <cortisollib.users.CortisolHttpUser> has extended the User <locust.User> so that it can read and process the logs that are written during the load test that happen in the background.

    wait_time = between(1, 5)

Our class defines a wait_time that will make the simulated users wait between 1 and 5 seconds after each task (see below) is executed. For more info see wait-time.

    @task
def hello_world(self):
...

Methods decorated with @task are the core of your cortisol file. For every running user, Locust creates a greenlet (micro-thread), that will call those methods.

    @task
def hello_world(self):
self.client.get("/hello")
self.client.get("/world")

@task(3)
def view_items(self):
...

We've declared two tasks by decorating two methods with @task, one of which has been given a higher weight (3). When our QuickstartUser runs it'll pick one of the declared tasks - in this case either hello_world or view_items - and execute it. Tasks are picked at random, but you can give them different weighting. The above configuration will make Locust three times more likely to pick view_items than hello_world. When a task has finished executing, the User will then sleep during its wait time (in this case between 1 and 5 seconds). After its wait time it'll pick a new task and keep repeating that.

Note that only methods decorated with @task will be picked, so you can define your own internal helper methods any way you like.

    self.client.get("/hello")
    @task(3)
def view_items(self):
for item_id in range(10):
self.client.get(f"/item?id={item_id}", name="/item")
time.sleep(1)

In the view_items task we load 10 different URLs by using a variable query parameter.