An Introduction to k6: Load Test Your API with Ease

Farhan LabibFarhan Labib
8 min read

Are you seeking a free, open-source load-testing tool for your RESTful API? Look no further than k6.

k6 is an open-source, developer-friendly tool for load, performance, and stress testing of APIs, micro-services, and websites. It is designed to be scriptable, scalable, and easy to use, even for those with little or no previous experience in load testing. With k6, you can simulate realistic traffic and measure how your system responds under load, so you can identify and fix performance issues before they impact your users.

One of the great things about k6 is that it allows you to code your testing scripts in JavaScript. If you prefer TypeScript, k6 even offers template support. Plus, you can generate testing scripts from OpenAPI or Postman.

Let’s move on to the next section for the setup and installation.

Setup

Setting up and installing k6 on different platforms is a breeze, and the process varies slightly depending on your operating system.

Windows

Windows users can easily install k6 using its MSI installer. Download the installer from the k6 website, run it like any other software installer, and you’re ready to use k6.

Mac

For Mac users, the more straightforward process to install k6 is by running a single command in the terminal:

brew install k6

Ubuntu

If you’re using Debian or Ubuntu, you can install k6 via the apt-get package manager. Run the following commands in your terminal:

sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69
echo "deb https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list
sudo apt-get update
sudo apt-get install k6

If you encounter any issues with getting the key due to firewalls or proxies, you can try using the alternative command below:

curl -s https://dl.k6.io/key.gpg | sudo apt-key add -

A Basic K6 Scripts

The basic key elements of a k6 script typically contain the following:

import http from "k6/http";
import { sleep } from "k6";

//option section

export let options = {
  vus: 10,
  duration: "30s"
};

//default function section

export default function() {
  const res = http.get("https://test-api.k6.io/public/crocodiles/");
  check(res, {
    "status is 200": (r) => r.status === 200
  });
  sleep(1);
}
  • options

The options section of a k6 script is used to define various configuration options for the load test. These options can include the number of virtual users (VUs) to simulate, the test duration, and more.

  • default

The default section of a k6 script is used to define a default function that will be executed for each VU during the test. This function can include any code necessary to simulate user behavior, such as sending HTTP requests, processing data, or performing other tasks.

  • checks

The checks section of a k6 script defines a set of assertions that evaluate the system's performance under test. These assertions can include checks for response times, error rates, and other metrics.

HTTP Requests

To create a simple GET request test case using the built-in http module in k6, you can follow these steps:

  1. Create a new JavaScript file in your working directory, e.g., script.js.

  2. Import the necessary modules, i.e., http and sleep, from the k6 library using the import statement:

import http from 'k6/http';
import { sleep } from 'k6';

3. Define the options object that specifies the test should simulate 10 virtual users (vus) and run for 30 seconds (duration).

export let options = {
  vus: 10, // number of virtual users
  duration: '30s', // duration of the test
};ja

4. Define a default function that represents the main logic of your test case. Inside this function, call the http.get() method to make a GET request to your API or any test API provided by k6:

export default function () {
  http.get('http://example.com/test');
  sleep(1);
}

5. Add a sleep statement at the end of the default function to simulate how real users use your system. Depending on your test scenario, you can set the value to a suitable number. For example, if you want to simulate users who make a request every second, set the sleep time to 1 second, like in the above example.

6. Save the script.js file and run the test using the k6 CLI by running the following command in your terminal:

k6 run script.js

Output Results

The following output will be displayed on your terminal.

When you run a k6 test, it will collect a set of default metrics and output them to the terminal after the test has finished. These metrics provide insights into how your API performs under load and can help you identify any bottlenecks or issues.

The following are the default metrics that k6 collects:

  • vus - the number of active virtual users (VUs) during the test

  • vus_max - the maximum number of VUs allocated for the test

  • iterations - the total number of times the default function is called by all VUs

  • iteration_duration - the total time it took to execute the default function across all VUs

  • data_received - the amount of data received by all VUs

  • data_sent - the amount of data sent by all VUs

  • checks - the rate of successful checks (will be discussed later)

In addition to these default metrics, k6 also generates the following output for each HTTP request generated during the test:

  • http_reqs - the total number of HTTP requests generated by k6

  • http_req_blocked - the time spent waiting for a free TCP connection before initiating the request

  • http_req_connecting - the time spent establishing a TCP connection with the remote host

  • http_req_tls_handshaking - the time spent on the TLS handshake with the remote host

  • http_req_sending - the time spent on sending data to the remote host

  • http_req_waiting - the time spent waiting for a response from the remote host

  • http_req_receiving - the time spent on receiving data from the remote host

  • http_req_duration - the total time taken for the request. This is calculated as the sum of http_req_sending, http_req_waiting, and http_req_receiving.

You can use these metrics and output to gain insights into the performance of your API and to identify any areas for optimization.

Configuring Load Test Scenario:

Options Design:

A common load-testing scenario for APIs is to gradually ramp up and down the number of virtual users (VUs) over time to simulate real-world usage patterns. The k6 options object allows you to specify these stages using the stages property. Here's an example of how you can configure your test to run in stages:

export let options = {
  stages: [
    { duration: '10s', target: 20 },   // Ramp up to 20 VUs in 10 seconds
    { duration: '1m10s', target: 10 }, // Stay at 10 VUs for 1 minute 10 seconds
    { duration: '10s', target: 0 },    // Ramp down to 0 VUs in 10 seconds
  ],
};

In this example, the stages array contains three objects, each representing a different stage of the test:

  1. The first stage ramps up the number of VUs from 0 to 20 over a period of 10 seconds.

  2. The second stage maintains a steady load of 10 VUs for 1 minute 10 seconds.

  3. The third stage ramps down the number of VUs from 10 to 0 over a period of 10 seconds.

Note that you can customize the duration and target values of each stage to match your specific requirements. Also, make sure that the duration of the entire test (the sum of all stage durations) is long enough to collect meaningful data and uncover any performance issues.

Checks:

When load testing APIs, it’s important to be able to assert the response that is returned by the API to ensure it meets your expected criteria. k6 provides a way to do this using the ‘check’ function. It’s important to note that the ‘check’ function does not halt the execution of the script.

HTTP Response and Fields For HTTP requests made in k6, an HTTP response object is returned that contains various fields such as

  • status

  • body

  • headers

  • timings

  • timings.blocked

  • timings.connecting

  • timings.tls_handshaking

  • timings.sending

  • timings.waiting

  • timings.receiving

  • timings.duration

Example: Checking if Status is 200 To check the status of an HTTP response in k6, you can first assign the response to a variable and then use the ‘check’ function with the desired assertion. For example, to assert that the response has a status of 200, you can use the following code:

export default function () {
  let res = http.get('http://example.com/test');
  check(res, {
    'is status 200': (r) => r.status === 200,
  });
}

Conclusion

To summarize what we have covered in this article —

  1. We started by describing what is k6 and then installing k6 on our local machine.

  2. Then learned about the basic key elements of the k6 script.

  3. After that, we moved on to creating simple test scripts based on the built-in http module provided by k6.

  4. Next, we briefly analyze the insights of k6 output.

  5. Moving forward, we explored how to configure options and checks to simulate real-life scenarios.

Previous Blog on k6:

Thanks for reading my article on An Introduction to k6. If you found it valuable, follow me on LinkedIn for more updates and insights on Software Quality Assurance. I’ll be sharing new articles and resources to help improve your process and deliver better products. Thanks again for reading, and I look forward to connecting with you!

3
Subscribe to my newsletter

Read articles from Farhan Labib directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Farhan Labib
Farhan Labib

3 Years+ experience in Software Quality Assurance Testing of Mobile and Web-Based Applications using Manual and Automation Testing. Experience in Functional, Exploratory, Regression, Cross-browser/platform, Compatibility, and GUI Testing. Knowledge in creating Test Plans, defining Test Scenarios and Test Cases, developing and maintaining test scripts, analyzing bugs, coordinating with the development team, and tracking the bug fixes till closure. Experienced in API & UI automation and Performance Testing. Easily collaborate with developers and project managers to accomplish milestones.