Scenario config file

I am trying to use config files to specify scenarios. I have one for each type of test (smoke, load, etc.). Config files seem to work fine with normal default scenarios but when I introduce custom scenarios it never pulls in the config correctly.

Also, precedence seems to be reversed. If I specify rps in options and the config file, it takes the options rps.

command line:

k6 run main.js --config config/load-test.json

config/load-test.json:

{
  "rps": 3,
  "thresholds": {
    "checks": ["rate>1"],
    "'http_req_duration{type:upload}'": ["p(95)<15000"],
    "'http_req_duration{type:download}'": ["p(95)<3000"],
    "'http_req_duration{type:normal}'": ["p(95)<250"]
  },
  "senerios": {
    "main": {
      "executor": "ramping-vus",
      "exec": "main",
      "stages": [
        { "duration": "1m", "target": 5 },
        { "duration": "1m", "target": 5 },
        { "duration": "1m", "target": 0 }
      ]
    },
    "retrieve": {
      "executor": "ramping-vus",
      "exec": "retrieve",
      "stages": [
        { "duration": "1m", "target": 5 },
        { "duration": "1m", "target": 5 },
        { "duration": "1m", "target": 0 }
      ]
    },
    "download": {
      "executor": "ramping-vus",
      "exec": "download",
      "stages": [
        { "duration": "1m", "target": 5 },
        { "duration": "1m", "target": 5 },
        { "duration": "1m", "target": 0 }
      ]
    },
    "search": {
      "executor": "ramping-vus",
      "exec": "search",
      "stages": [
        { "duration": "1m", "target": 5 },
        { "duration": "1m", "target": 5 },
        { "duration": "1m", "target": 0 }
      ]
    }
  }
}

error:


          /\      |‾‾| /‾‾/   /‾‾/   
     /\  /  \     |  |/  /   /  /    
    /  \/    \    |     (   /   ‾‾\  
   /          \   |  |\  \ |  (‾)  | 
  / __________ \  |__| \__\ \_____/ .io

ERRO[0000] There were problems with the specified script configuration:
        - executor default: function 'default' not found in exports 

It is supposed to, the exported script options have a higher precedence than the JSON config. In ascending of order precedence, the options are consolidated like this: defaults < JSON config < script options < environment variables < CLI flags, see the options docs.

I tested this and scenarios from a JSON config files was correctly picked up by k6:

$ cat config.json 
{
    "scenarios": {
        "foo": {
            "executor": "constant-arrival-rate",
            "rate": 10,
            "timeUnit": "1s",
            "duration": "1m",
            "preAllocatedVUs": 20
        }
    }
}

$ cat http_get.js 
import http from 'k6/http';

export default function () {
  const response = http.get("https://test-api.k6.io/");
};

$ k6 run --config config.json http_get.js 

          /\      |‾‾| /‾‾/   /‾‾/   
     /\  /  \     |  |/  /   /  /    
    /  \/    \    |     (   /   ‾‾\  
   /          \   |  |\  \ |  (‾)  | 
  / __________ \  |__| \__\ \_____/ .io

  execution: local
     script: http_get.js
     output: -

  scenarios: (100.00%) 1 scenario, 20 max VUs, 1m30s max duration (incl. graceful stop):
           * foo: 10.00 iterations/s for 1m0s (maxVUs: 20, gracefulStop: 30s)
 ...

So, I guess that your exported script options contained one of these: scenarios / duration / stages /iterations, which overwrote the scenarios from the JSON config file.

And if this config precedence doesn’t work very well for you, there’s an alternative that’s very easy to use! :slight_smile: You can open() your JSON config files in your script’s init context, use JSON.parse() to parse them, and then re-export them (or parts of them) as the exported script options. And you can use k6 environment variables to dynamically load different config files in different test runs. For example, you can have this script:

import http from "k6/http";

let myOptions = JSON.parse(open(__ENV.TEST_TYPE));

export let options = {
    scenarios: myOptions.scenarios
    // ... other options, or just re-export the whole myOptions
};

export default function () {
    // ... 
}

And then run it with k6 run --env TEST_TYPE=smoke test.js, k6 run --env TEST_TYPE=load test.js, etc.

Btw, just saw your config file - consider using ramping-arrival-rate as an executor, instead of ramping-vus and rps. Besides rps being a bit tricky to use right, there are other benefits: https://k6.io/docs/using-k6/scenarios/arrival-rate

I was actually just looking at that! Yea rps is a little tricky!

Ok that make sense. I think I read the defaults a being the options defined in the script.

I’ll try it!