k6

A modern load testing tool, using Go and JavaScript

"like unit testing, for performance"

k6 is a modern load testing tool, building on Load Impact's years of experience. It provides a clean, approachable JavaScript scripting API, distributed and cloud execution, and orchestration via a REST API.

Get Started    Documentation

Search results for "{{ search.query }}"

No results found for "{{search.query}}". 
View All Results

What is a check?

Checks are like asserts but differ in that they don't halt execution, instead they just store the result of the check, pass or fail, and let the script execution continue. Checks are great for codifying assertions relating to HTTP requests/responses, making sure the response code is 2xx for example:

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

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

In the above example one check was specified but you can add as many as you need in a call to check(). When the above script is run you can see how k6 displays the results of the check calls in the following output:

In the output above you can see that our check "is status 200" was successful 100% of the times it was called.

You may also add multiple checks within a single check() statement, like this:

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

export default function() {
  let res = http.get("http://test.loadimpact.com/");
  check(res, {
    "is status 200": (r) => r.status === 200,
    "body size is 1176 bytes": (r) => r.body.length == 1176
  });
}

Using checks in a CI setting

One important thing to understand regarding checks is that a failed check will not fail the whole load test.

Checks help keeping your code organized and easy to read, but when you're running a load test in a CI test suite you may want to check for error conditions that fail the whole load test. In this case you may want to combine checks with thresholds to get what you want:

import http from "k6/http";
import { check } from "k6";
import { Rate } from "k6/metrics";

export let errorRate = new Rate("errors");

export let options = {
  thresholds: {
    "errors": ["rate<0.1"], // <10% errors
  }
};

export default function() {
  check(http.get("http://httpbin.org"), {
    "status is 200": (r) => r.status == 200
  }) || errorRate.add(1);
};

The above script declares a custom Rate metric (called "errors") to hold information about the errors we have seen during the test, then it uses a threshold on that custom metric to fail the test when it encounters too many errors. If we replace the "http://httpbin.org" URL with one that will generate an error, k6 will exit with a nonzero exit value, indicating a FAIL result to e.g. a CI system that may have executed it:

As you can see above, the exit code generated by k6 after this run was 99. Any nonzero exit code is commonly interpreted by Un*x shells, CI servers and monitoring systems as a "failure".

Note also the expression check() || errorRate.add(1). When any one of the check conditions inside a check() call fails, check() returns false, which causes the code after || to be executed. In this case it means we add one data point to our Rate metric. Only if all check conditions pass will check() return true.

See check() in the script API reference for more details on how check() works.

Checks