Hi, im trying to put together a generic test code which:
- reads in scenario configurations from a config file
- generates scenario configuration
- generates VU code functions
- and exports them
I succeeded to create such a script, but with a limitation. I can only export a static list of functions and the optimal would be to dynamically export all the generated functions.
This is how a config.json looks like:
{
"scenarios": [
{
"hostname": "interesting-hostname.com",
"schema": "https",
"path": "/team/links",
"exec": "team_links",
"executor": "constant-arrival-rate",
"duration": "30s",
"rate": 40,
"timeUnit": "1s",
"preAllocatedVUs": 2,
"maxVUs": 60
},
{
"hostname": "interesting-hostname.com",
"schema": "https",
"path": "/status/elastic",
"exec": "status_elastic",
"executor": "constant-arrival-rate",
"duration": "30s",
"rate": 30,
"timeUnit": "1s",
"preAllocatedVUs": 2,
"maxVUs": 60
}
]
}
And this is the script code, with commented out attempts on the bottom section to dynamically export the functions:
import http from 'k6/http';
import { group } from 'k6';
import { SharedArray } from 'k6/data';
// All heavy work (opening and processing big files for example) should be done inside here.
// This way it will happen only once and the result will be shared between all VUs, saving time and memory.
const scenariosConfig = new SharedArray('scenario configurations', function () {
const configContent = JSON.parse(open('/test_folder/config.json'));
console.log(JSON.stringify(configContent));
const extractedConfigData = configContent.scenarios; // Change 'specific_key' to the key you want to extract
return extractedConfigData; // extractedData must be an array
});
function generateScenarios(pScenariosConfig) {
const scenariosOptions = {}
pScenariosConfig.forEach(scenario => {
scenariosOptions[scenario.exec] = {
executor: scenario.executor,
exec: scenario.exec,
duration: scenario.duration,
rate: scenario.rate,
timeUnit: scenario.timeUnit,
preAllocatedVUs: scenario.preAllocatedVUs,
maxVUs: scenario.maxVUs
};
});
return scenariosOptions;
}
export const options = {
discardResponseBodies: true,
scenarios: generateScenarios(scenariosConfig),
};
function defineApiCall(scenario) {
return function () {
group(scenario.exec, () => {
http.get(scenario.schema + '://' + scenario.hostname + scenario.path, {
tags: { my_custom_tag: scenario.exec },
});
});
};
}
// Define functions dynamically based on config
const apiCalls = {};
scenariosConfig.forEach(scenario => {
const apiCallName = scenario.exec; // Get function name from "exec" property
apiCalls[apiCallName] = defineApiCall(scenario);
});
// >>> This fails with: 'import' and 'export' may only appear at the top level
//// Dynamically export the generated function individually
//const apiCallNames = Object.keys(apiCalls); // Get function names as an array
//
//for (const name of apiCallNames) {
// export function [name]() {
// return apiCalls[name];
// }
//}
// >>> This fails with: could not load JS test 'file:///test_folder/test_multiple_scenarios_groups.js': no exported functions in script"
//// Dynamically export the generated functions as an object
//const apiCallNames = Object.keys(apiCalls); // Get function names as an array
//
//const exportedApiCalls = {};
//for (const name of apiCallNames) {
// exportedApiCalls[name] = apiCalls[name];
//}
//export { exportedApiCalls };
// >>> This is not dynamic, but works...
export const { team_links, status_elastic } = apiCalls;
Im not a JS guru and looks like my problem is not directly k6 related(well, as i see there is a k6 limitation to use the export only on top level, or it expects individual function exports), but if anyone has relevant JS expertise or did a similar script, please help me figure out how to dinamically export the generated functions so k6 can use them and the only file which has to be changed is the configuration.