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

Archives for bundling/sharing a test

What is an archive?

When the complexity of a k6 test goes beyond a single JS file it quickly becomes cumbersome to find and bundle up all the dependencies (JS, open()'ed data files, TLS client certs etc.). There is a need for a native way to bundle and distribute/share a test. That is what k6 archives are for.

A k6 archive is simply a tar file with all files needed to execute a k6 test.

How to create and run an archive

Let's say that you normally execute a test using:

k6 run script.js

Now if you replace run with archive k6 will run the init stage of the code to determine which JS files are being imported and what data files are being open()'ed and bundles all of the files up into a tar file:

k6 archive script.js

This would produce a tar file on disk called archive.tar (you can change that by setting -O filename.tar). It's also easy to run an archive, as k6 run is compatible with archive files you can execute:

Overriding options

As always you can override options using CLI flags or environment variables when running an archive.

k6 run archive.tar

Use cases

Archive files have a variety of use cases, but they all share the common need to bundle of a test's files into a single file for easy distribution.

Sharing a test
By bundling up a test into an archive it's easy to share the test with your team mates by simply storing or sending a single tar file. As we saw in the previous section, your team mates can execute the archive by running k6 run archive.tar.

Preparing tests for CI
If you have a complex CI pipeline and your load tests are separated from your application code, you could store k6 archives as build artefacts whenever the load test source code is changed, and then pull in those k6 archives from the artefacts storage for test execution as needed.

Load Impact Cloud Execution (private beta)
Load Impact offers a commercial service for running large scale and geographically distributed load tests on managed cloud infrastructure. Cloud executed tests are triggered from the k6 command-line via the k6 cloud script.js command (similar to k6 run) which will trigger an implicit creation of a k6 archive that is uploaded and distributed to Load Impact load generators for execution.

Clustered Execution (future)
In the future (roadmap) k6 will support a clustered execution mode that will enable tests to be run across more than one node. This mode of execution is also likely to make use of the archive functionality to distribute the test files to all participating nodes.

Contents of an archive file

An archive contains the original source of the JS code, any open()'ed data files, SSL/TLS client certificates as well as a metadata.json with all the options (a cascading of the options set on the CLI, via Environment variables and in-script options (export let options = {...})).

Let's create an archive from the following sample test. Here is the layout in the filesystem of the files:

/home/johndoe/tests/api-test/script.js
/home/johndoe/tests/api-test/utils/common.js
/home/johndoe/tests/api-test/endpoints/login.js
/home/johndoe/tests/api-test/endpoints/search.js
/home/johndoe/tests/api-test/node_modules/somelib/lib.js
/home/johndoe/tests/api-test/data/users.json

Now, if the current working directory is /home/johndoe/tests/api-test/ and we run k6 archive script.js we'd get a tar file called archive.tar (you can change the name of the file using -O filename.tar). The contents of the archive.tar would look like something like this:

data
files
  | home
  |----| nobody <-- the username has been anonymized (see section further down)
  |----|----| tests
  |----|----|----| api-test
  |----|----|----|----| data
  |----|----|----|----|----| users.json
metadata.json
scripts
  | home
  |----| nobody <-- the username has been anonymized (see section further down)
  |----|----| tests
  |----|----|----| api-test
  |----|----|----|----| script.js
  |----|----|----|----| utils
  |----|----|----|----|----| common.js
  |----|----|----|----| endpoints
  |----|----|----|----|----| login.js
  |----|----|----|----|----| search.js
  |----|----|----|----| node_modules
  |----|----|----|----|----| somelib
  |----|----|----|----|----|----| lib.js

Breaking down the file structure we get:

  • data: The source code of the main JS file (script.js in this example)
  • files: Contains the full original directory tree of all open()'ed data files
  • metadata.json: The resolved "default" options for this test based on CLI flags, Environment variables and in-script options.
  • scripts: Contains the full original directory tree of all import'ed JS dependencies

The metadata.json files looks like this:

{
  "type": "js",
  "options": {
    "paused": null,
    "vus": null,
    "vusMax": null,
    "duration": null,
    "iterations": null,
    "stages": null,
    "setupTimeout": null,
    "teardownTimeout": null,
    "rps": null,
    "maxRedirects": null,
    "userAgent": null,
    "batch": null,
    "batchPerHost": null,
    "httpDebug": null,
    "insecureSkipTLSVerify": null,
    "tlsCipherSuites": null,
    "tlsVersion": {
      "min": "",
      "max": ""
    },
    "tlsAuth": null,
    "throw": null,
    "thresholds": null,
    "blacklistIPs": null,
    "hosts": null,
    "noConnectionReuse": null,
    "ext": null,
    "summaryTrendStats": null,
    "systemTags": [
      "url",
      "name",
      "check",
      "error",
      "tls_version",
      "method",
      "subproto",
      "status",
      "group",
      "proto"
    ],
    "tags": null
  },
  "filename": "/home/johndoe/tests/api-test/script.js",
  "pwd": "/home/johndoe/tests/api-test/",
  "env": {}
}

What an archive file does not contain

We try to be cautious with what we include in an archive file. Some things we do to that end:

  • We anonymize the username found in any path to JS and data file dependencies
  • We don't include and environment variables from the system in the archive

Archives for bundling/sharing a test