Performance Testing with k6 - 02 - Multiple Tasks
Published: 2021-05-05 09:35:22

In the first part of this series we learnt about creating a very basic k6 test. In this tutorial we will create some more realistic and interesting tests.
 For that we better have a real App to test. For simplicity and because I'm familiar with it I've chosen [ownCloud](https://owncloud.com/), a file hosting and sharing 
 solution similar to Dropbox.

The easiest way to get a test ownCloud instance up and running is to use docker.

Just run: `docker run -p 8080:8080 --name owncloud owncloud/server`.

This magic `docker run` command should give you a fresh ownCloud installation that can be reached at http://localhost:8080.

There is one user pre-setup called `admin` with the super-secure password `admin`. You can login into the UI and upload files, create new users, share files and folders, etc.
After having played a bit with ownCloud itself, let's get back to k6.

### Test Creating file
Create a file (`script.js`) and add the following contents
```
import http from 'k6/http'
import encoding from 'k6/encoding'
import { check } from 'k6'
import { uuidv4 } from 'https://jslib.k6.io/k6-utils/1.0.0/index.js'

export let options = {
  iterations: 100,
  vus: 10
}

export default function() {
  const fileName = `${uuidv4()}.txt`
  const url = `http://localhost:8080/remote.php/webdav/${fileName}`
  const body = 'some content'
  const headers = {
    'Authorization': 'Basic ' + encoding.b64encode('admin:admin'),
    'Content-Type': 'application/x-www-form-urlencoded'
  }

  const response = http.request('PUT', url, body, { headers: headers })
  check(response, {
    'status is 201': (r) => r.status === 201 || 204
  })
}
```

1. Here, in the `options` object we are providing `iterations: 100` and `vus: 10` i.e. 100 test runs will be divided among 10 vus. To specify how `iterations` is divided among `vus` we can provide `executor` options. For more details about executors check https://k6.io/docs/using-k6/scenarios/executors/

2. We are sending a `PUT` request to the owncloud endpoint to create a file. For authorization header we are using user `admin` with password `admin` that we created. So, basically the `10 vus` in options will be using `admin` user authorization

3. Since it's not possible to create multiple files with the same name in owncloud, we are using [uuid](https://en.wikipedia.org/wiki/Universally_unique_identifier) in `fileName`

### Test deleting file
```
import http from 'k6/http'
import encoding from 'k6/encoding'
import { check } from 'k6'
import { uuidv4 } from 'https://jslib.k6.io/k6-utils/1.0.0/index.js'

export let options = {
  iterations: 100,
  vus: 10
}

const createFile = url => {
  const body = 'some content'
  const headers = {
    'Authorization': 'Basic ' + encoding.b64encode('admin:admin'),
    'Content-Type': 'application/x-www-form-urlencoded'
  }

  const response = http.request('PUT', url, body, { headers: headers })
  check(response, {
    'status is 201': (r) => r.status === 201 || 204
  })
}

const deleteFile = (url) => {
  const headers = {
    'Authorization': 'Basic ' + encoding.b64encode('admin:admin')
  }
  const response = http.request('DELETE', url, undefined, { headers: headers })
  check(response, {
    'status is 204': (r) => r.status === 204
  })
}

export default function() {
  const fileName = `${uuidv4()}.txt`
  const url = `http://localhost:8080/remote.php/webdav/${fileName}`
  createFile(url)
  deleteFile(url)
}
```

Here, we are adding code to delete a file. Also, I have separated the logic for file creation and deletion into two separate functions `createFile` and `deleteFile`.

### Settings Stages
We can ramp up/down the VU level during the test using `stages`  The `options.stages` property allows you to configure ramping behaviour.

```
...
export let options = {
  stages: [
    { duration: '30s', target: 20 },
    { duration: '1m30s', target: 10 },
    { duration: '20s', target: 0 }
  ]
}
...
```
- First Stage(30s duration): Initially at the start will have 1 VU and then k6 will linearly ramp up from 1VU to 20VUs during the span of 30 seconds.
- Second Stage(1m30s duration): At the start of this stage we will have 20Vus from the first stage, but it will linearly ramp down to 10Vus at the end of the duration of this stage.
- Third Stage(20s duration): During this stage 10Vus from the second stage will linearly ramp down to zero at the end of 20 seconds.

Now if we run the test using `k6 run script.js`:

![Screenshot from 2021-04-28 09-08-56](https://user-images.githubusercontent.com/34328907/116341872-6baf0d00-a801-11eb-97a4-340fbeb165ee.png)

As shown in above screenshot our test runs for a total duration of `2m20s`(30s + 1m30s + 20s), while `vus` `max` is `20` (end of the first stage) and it's `min` is `1` which happens at the beginning of the first stage.