How would I go about executing multiple script files in a single run?

Development team has provided Postman collection for performance testing. There would be around 20 collection. Each collection represents end to end micro services. I am using Postman to K6 converter. It gives me 20 JS files. VU level , stages/options and threshold/ checks needs to be different for each K6 JS file. This project would be added inside Git. We need to define pipeline to execute all the JS files.

APPROACH 1 -
I decide to write let’s say start.js and then call all other 20 JS files within start.js. I will invoke start.js from Git yml file.
Sample start.js looks as below-

import "./PostmanScripts/libs/shim/core.js";
import "./PostmanScripts/libs/shim/urijs.js";

import { group, http, sleep } from 'k6';
import startSiteTest from "./PostmanScripts/Test/Site/startSiteTest.js";

export let options = {
  stages: testData.siteCRUDOptions,
  teardownTimeout: testData.teardownTimeout,
  thresholds: testData.thresholds
}

postman[Symbol.for("initial")]({
  options,
  collection: {
  },
  environment: {
    AUTH0_BASE_URL: `${__ENV.AUTH0_BASE_URL}`,
  }
});

export default function () {
  //Call Test Collection 1 - Create Site
  startSiteTest();
  sleep(2);
  startFreeTrailTest();
}

However,
postman[Symbol.for("initial")]({

has to be declared once. It is mandatory that it contains VU options. Due to this, I cannot define options, VU stages, threshold inside individual JS files.

I want something like below to achieve my goal. However, it is not working.
Inside Start.js –
I will add
postman[Symbol.for("initial")]({

Here I will define all the environment variables.

In each individual JS file, lets say test.js I will define following.

import http from "k6/http";

import * as testData from "../../TestData/siteCRUDOptions.js";

export let options = {
  stages: [
    { duration: "10s", target: 2 },
    { duration: "10s", target: 3 },
  ]
}


export default function() {
  console.log("ENV " +  `${__ENV.AUTH0_BASE_URL}`);
  http.get("http://test.loadimpact.com");
};

Now, I will call start.js from Git.
However, with this approach VU would not get spanned. It seems not allowed. Everytime, test.js or any other file gets called only with 1 VU and 1 Iteration.

APPROACH 2 –
Create shell script, lets say start.sh. It contains all the JS files calls. Invoke start.js from Git, define it in yml file

 k6 run PostmanScripts/Test/Site/test.js
 k6 run PostmanScripts/Test/Site/test2.js


APPROACH 3 –  Write a docker compose script. This would start up a docker container for each test and run it inside there
services:
  k6_test:
    image: loadimpact/k6
    container_name: test_k6
    command: k6 run /tests/test_spec.js

  k6_test2:
    image: loadimpact/k6
    container_name: test2_k6
    command: k6 run /tests/test2_spec.js

Which would be the better approach? Is there any other way?

Adding @Murat

Thank you for posting ! :pray:t3:

Let me see if I got this right. You’d like to be able to split your tests into multiple files and execute them as a test suite, right?

You’re on the right track with both of your alternatives, however; only the default function and options of the entry file will be read, as you’ve noticed. To go around this, you’d need to manually execute the default function of the other test files from your entry files default function.

I’ve provided a working example below, showcasing what you’re trying to accomplish.

start.js

import http from "k6/http";
import { sleep, check } from "k6";
import runTestOne from "./test1.js";
import runTestTwo from "./test2.js";

export default function() {
    runTestOne();
    runTestTwo();
};

It imports the exported default function from each test file and runs them as part of the default function of start.js. Your actual test files would then look a little something like this:

test1.js

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

export default function() {
  let res = http.get("http://test.loadimpact.com");
  sleep(1);

  check(res, {
      "status is 200": (r) => r.status === 200,
      "response body": (r) => r.body.indexOf("Feel free to browse")
  });
}

test2.js

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

export default function() {
  let res = http.get("http://something-else.example.com");
  sleep(1);

  check(res, {
      "status is 200": (r) => r.status === 200,
      "response body": (r) => r.body.indexOf("Im something completely different")
  });
}

Feel free to reply to this thread if you need any additional assistance. :+1:t2:

how about the test1.js and test2.js options function, how can i set the distribution of test1.js to run stagesA and test2.js to run stagesB?

You currently can’t at least not easily. You can try to approximate things by keeping time internally in the VUs, but it will probably be a bit flaky. https://github.com/loadimpact/k6/issues/1342 is a proposal in how we can quickly implement that soon after https://github.com/loadimpact/k6/pull/1007 is done.

1 Like