Performance Testing with k6 - 01 - Getting Started
Published: 2021-05-05 09:32:17

Let's suppose your website/web-app/blog gets popular overnight ( Imagine Elon Musk tweeting about your web app ) and there's a massive spike in the number of visitors/users
 accessing your web app. This swelling traffic can overwhelm the web server causing an unintentional distributed denial of service (DDOS) attack. This is a nightmare scenario as people cannot access your web-app.

Now, how do we determine how many users your backend infrastructure can handle?

To answer that, and other performance questions, we have a couple of great performance-testing tools available out there. One of them is [k6](https://k6.io/)

### What is k6?
k6 is a free and open-source load testing tool written in Go programming language. But you don't need to know `Go` to write tests using k6.
If you are familiar with the basics of ES2015/ES6, you won't have any headache writing k6 tests.

### Installation
To install k6 in your local machine follow the instructions provided here https://k6.io/docs/getting-started/installation/ 

I am using ubuntu `18.04` but even if you are using another operating system you can follow along.

### Your first test: 

k6 is based on the concept of `virtual users` (VUs) that is supposed to simulate the real-time traffic and then execute the script in parallel.

As a rule of thumb, each k6 script must contain at least an exported `default` function, unless you are using [Scenarios](https://k6.io/docs/using-k6/scenarios/).
This `default` function is the entry point for the VUs, similar to the `main()` function in Java and other programming languages.

Let's write a simple k6 script that makes a `GET` request to a test website:

`Disclaimer: Make sure load testing is allowed by your web host so that you don't violate their terms of service. In our example, we will be testing a test website  https://test.loadimpact.com/`

Create a file `test.js` and add the following content:
```
import { check } from "k6";
import http from "k6/http";

export default function() {
  let response = http.get("https://test.loadimpact.com/");
  check(response, {
    "is status 200": (r) => r.status === 200
  });
};
```

Unlike many other JavaScript runtimes, most of the operations in k6 are synchronous i.e. no need to use callbacks and promises.
For example;
```
http.get(...).then(res =>....)
```
OR
```
let response = await http.get(....)
```
is not needed and we can use synchronous code mentioned in `test.js` of our example.

### Running tests
Then run the k6 script using this command:
```
k6 run test.js
```

By default, if nothing is specified (as in the above command), k6 runs a script with only 1 VU and for 1 iteration only. It is useful for debugging, but it's not load testing.

Here a virtual user sends a `get` request to `https://test.loadimpact.com/` and the response status code is checked.

Now we'll run a k6 test with more than 10 virtual users and for a duration of 5 seconds:

```
 k6 run --vus 10 --duration 5s test.js
 ```

![Screenshot from 2021-04-27 15-34-44](https://user-images.githubusercontent.com/34328907/116222217-1bd33600-a76e-11eb-8ea5-86874d07cb00.png)

From the above screenshot:
- `checks = 100%`: all of the test run passed
- `vus = 10`: 10 virtual users (as provided in the run command)
- `iterations = 126`: total number of iterations the test ran. This may vary with each run as we didn't specify the iterations ourself


Now, instead of doing `--vus ... --durations .... --iterations....` we can also `export` an `options` object to set any options that we want. For example:
```
export let options = {
    vus: 10,
    duration: 5s
};
export default function() { .... }
```


### What's next?
That all was nice and easy, but not very realistic. It does not matter if you want to test a web frontend or an API, just sending a GET requests does not simulate the user's behavior. In the next parts of this series, we will learn more about k6 in a more realistic way.