k6 Performance Testing - udemy

Very good at showing the basics of k6 and load/performance testing in general.

During the course I knew an interesting webservice: https://designer.mocky.io/

Basic Concepts

Test Types:

Acronyms:

Test Types

Smoke Testing

doc

Validate that your script works and that the system performs adequately under minimal load.

code

Run the code below with k6 run <script.js>.

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

export const options = {
  // only one Virtual User
  vus: 1,
  duration: '30s'
}

export default function() {
  http.get('https://test.k6.io');
  sleep(1);
  http.get('https://test.k6.io/contact.php');
  sleep(2);
  http.get('https://test.k6.io/news.php');
  sleep(2);
}

Average Load Testing

doc

Asses how your system performs under expected normal conditions (aka typical load).

k6 average load testing.png

code

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

export const options = {
  // Key configurations for avg load test in this section
  stages: [
    // traffic ramp-up from 1 to 100 users over 5 minutes.
    { duration: '5m', target: 100 },
    // stay at 100 users for 30 minutes
    { duration: '30m', target: 100 },
    // ramp-down to 0 users
    { duration: '5m', target: 0 },
  ],
};

export default () => {
  const urlRes = http.get('https://test-api.k6.io');
  sleep(1);
  // Here you can have more steps or complex script...
};

Stress Testing

doc

Asses how a system performs at its limits when load exceeds the expected average

k6 stress testing.png

code

pretty similar to average load testing, but with a greater target

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

export const options = {
  // Key configurations for Stress in this section
  stages: [
    // traffic ramp-up from 1 to a higher 200 users over 10 minutes.
    { duration: '10m', target: 200 },
    // stay at higher 200 users for 30 minutes
    { duration: '30m', target: 200 },
    // ramp-down to 0 users
    { duration: '5m', target: 0 },
  ],
};

export default () => {
  const urlRes = http.get('https://test-api.k6.io');
  sleep(1);
  // Here you can have more steps or complex script...
};

Spike Testing

Verifies whether the system survives and performs under sudden and massive rushes of utilization.

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

export const options = {
  // Key configurations for spike in this section
  stages: [
    // fast ramp-up to a high point
    { duration: '2m', target: 2000 },

    // No plateau

    // quick ramp-down to 0 users
    { duration: '1m', target: 0 },
  ],
};

export default () => {
  const urlRes = http.get('https://test-api.k6.io');
  sleep(1);
  // Add only the processes that will be on high demand
};

Breakpoint Testing

Aims to find system limits.

Reasons to know limits include:

Considerations:

Soak Testing

Assess the reliability and performance of your system over extended periods (e.g.: 12h-24h).

Analyzing the system's degradation of performance and resource consumption over extended periods.

It's basically the same as the average load testing, but for extended periods of time in the plateau stage (do not change the ramp up/down stages).

You typically run this test to:


k6 scripts

structure of a k6 script

// import some stuff from k6
// ...

console.log('-- init stage --')

// this is happening during init stage
export const options = {
  // configure some options
};



export function setup() {
  console.log('-- setup stage --')
}

export default function() {
  console.log('-- VU stage --')
}

export function teardown() {
  console.log('-- teardown stage --')
}

environment variables

We can get the content of environment variables inside a k6 script by using __ENV.<varname>.

Example:

const baseUrl = __ENV.BASE_URL

http responses

official docs

import http from 'k6/http';

export default function() {
  // save the response in a var
  const res = http.get('https://test.k6.io/');

  // try res.<c-space> to see the options
  console.log(res.status)
}

assertions

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

export default function() {
  const res = http.get('https://test.k6.io/')
  check(res.status, {
    'status is 200': (statusCode) => statusCode === 200
  });
}

jsutils - random numbers, random strings, etc.

random intenger:

import { randomIntBetween } from 'https://jslib.k6.io/k6-utils/1.2.0/index.js';

// ...
const my_int = randomIntBetween(1, 5);

It's useful to use sleep() with a random number, to prevent a block of requests when testing with several VUs.

random string

import { randomString } from 'https://jslib.k6.io/k6-utils/1.2.0/index.js';

// ...
const username = `test_${randomString(8)}`; // random string with 8 chars

random item from an array

import { randomItem } from 'https://jslib.k6.io/k6-utils/1.2.0/index.js';

// ...
const item = randomItem(my_array);

thresholds

example:

// ...
export const options = {
  thresholds: {
    http_req_duration: [{

      // 99% must be "solved" in less than 1 second
      threshold: "p(99) < 1000",

      // abort the test if the threshold is crossed, but...
      abortOnFail: true,

      // ... wait for 10s before considering the 'abortOnFail'
      delayAbortEval: "10s"
    }]
  },
  //...
}

metric types and aggregation methods

metric type description
Counter cumulatively sums added values.
Gauge stores the min, max and last values added to it.
Rate tracks the percentage of added values that are non-zero.
Trend calculates statistics on the added values (min, max, average, and percentiles).

suggestions for improvements

custom thresholds

One important thing to teach is the abortOnFail option, which is specially useful when doing breakpoint test. Don't forget to mention the delayAbortEval option too!

Here's an example:

export const options = {
  thresholds: {
    http_req_duration: [{

      // 99% must be "solved" in less than 1 second
      threshold: "p(99) < 1000",

      // abort the test if the threshold is crossed, but...
      abortOnFail: true,

      // ... wait for 10s before considering the 'abortOnFail'
      delayAbortEval: "10s"
    }]
  },
  //...
}

show some options for a better final output

Use case: I used k6 at my job, and after all the tests the managers asked for a report to summarize the conclusions.

We had to copy'n'paste the k6 output and do some manual work to get only the info we wanted. It would be awesome if the course taught this kind of thing...

Examples of useful little things I learned from the docs:

Another thing I'd like to know but didn't looked that much in the docs: How to specify the few metrics I'm interested in?

Example: I only want the http_req_duration and http_req_waiting.

how to better organize your code

This page in the k6 docs gives good hints about better organizing the code. I think the course should mention this kind of thing.

examples for specific tests

The Examples page can be an awesome inspiration for examples to be shown and explained in the course.

This article also can give some nice insights for k6 things to teach.