Grafana k6 is an open-source load testing tool that makes performance testing easy and productive for engineering teams. k6 has packages for Linux, Mac, and Windows, but you can also use a Docker container or a standalone binary. Steps on how to install k6 are very well described on their website (along with other great documentation). [and I will not duplicate the steps here.]
In this article, we will focus on writing a performance script for the Petstore API (Application Programming Interface), starting from one simple JavaScript file and improving it further until a more reliable and maintainable performance test solution is achieved.
Author: Andrei Zarjitchi
The performance script that we want to create is described by the following flow:
create a new user (POST /user)
get the user details using the provided username (GET /user/{username})
delete the added user (DELETE /user/{username})
Our first performance test script that reproduces this flow would look like this:
As you can see above, we have a default function that k6 uses to define the entry point for our virtual users. Every k6 performance script needs to have a default function.
The default function contains all the 3 requests defined in our flow.
To run this script, we use the following command:
k6 run --vus 1 --duration 2s .\k6-petstore-v1.js
We are not interested in verifying the performance of the Pet Store app in this post, so for now, we will run our script with only one VU. When we run this performance script with k6, we will see the output from the image below.
At this point, our performance script is not easy to read or maintain.
Furthermore, the results of this script are not particularly useful as we cannot see the http_req_duration for each type of request (POST /user, GET /user/{username} or DELETE / user/{username}). The only http_req_duration that is shown in the results overview is calculated, in this case, for all the 3 requests.
Adding tags and thresholds
To see the results for each request, we will further improve our script by adding a tag to the requests and by defining the thresholds for each tag, too.
In the following screenshot, we have the results after adding tags to each request. By adding thresholds for each tag, we can now see the http_req_duration for each request. Another benefit of using thresholds is that k6 will let you know when a certain threshold has failed. In the image below, we can see that CreateUser request failed because the desired threshold for 90th percentile (set to 100ms in our script) was reached.
Model each request as a class
At this point our script is crowded and difficult to read and maintain as it contains all the requests and their checks in the same JavaScript file. Also, we cannot reuse any parts of the performance script.
The next change we will make to our script is to move each request (POST, GET, DELETE) and its checks in a separate JavaScript file and model it as a class. In this way our performance script becomes more readable, and we can also reuse the same requests in different performance scripts.
Once we move each request to a separate file, our solution structure will look like this:
And our performance script is now smaller and easier to read, as we can see below.