-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Description
I'm creating this issue as a place to discuss possible ways for k6 to execute multiple distinct scripts in a single run. This is prompted by https://community.k6.io/t/running-10-test-cases-out-of-100/448, and other similar previous user inquiries.
Something like this can currently be achieved by a simple shell script that sequentially calls k6 run "$script_path" for all files in a folder, but that workaround is not very convenient without an external output like InfluxDB. It also doesn't work well with k6 cloud, and isn't efficient in general (each separate k6 run has to re-initialize its VUs). GitLab’s performance testing tool is probably also worth investigating...
I also have a vague idea how we can implement something like "test suites" natively in k6 after #1007 is done, and do it relatively easily (:tm: :sweat_smile: ). To get 80% of the way there, we just need to implement one minor (sort-of-already-planned) improvement on the currently planned #1007 feature set 🎉. Instead of specifying startTime: "30s" for an executor, users should be able to specify startAfter: "someOtherExecutorName". This will be very easy to implement (minor changes in the config validation, here and here).
This will add a lot of convenience in general, so it's probably worth doing just for that. But it will also, when used with the exec option for each executor (to run some non-default function), probably satisfy the "test suite" requirements of the majority of our users, albeit with some manual configuration work (which we can ameliorate with some JS helper functions).
At a later point, to satisfy the remaining minority of more complex use cases, and to achieve something similar to k6 run test1.js test2.js test3.js (and, crucially, k6 cloud test1.js test2.js test3.js), we can make another (somewhat more tricky) change to k6. We need to transform the current local.ExecutionScheduler into just another executor. That is, we will add a new composite executor type that will be able to contain other executors. I may be wrong, but because of the new executor architecture in k6, and because we already have 95% of the required code in local.ExecutionScheduler, I think this will actually be very straightforward to do 🎉 😄 At least on the execution side, there will be some complexity elsewhere.
To illustrate, for example, if test1.js has vus: 20, duration: "30s" in its exported options, test2.js has iterations: 1000, vus: 20, and test3.js has something like this:
export let options = {
execution: {
constant_arr_rate: {
type: "constant-arrival-rate",
rate: 20,
duration: "1m",
preAllocatedVUs: 10,
},
per_vu_iters: {
type: "per-vu-iterations",
vus: 10,
iterations: 100,
maxDuration: "1m"
},
},
// ...
}then, when you run k6 run test1.js test2.js test3.js, it should be relatively easy to produce something like this as the final derived options.execution value:
{
"test1.js": {
type: "composite",
exec: "test1.js/default", // this is actually the tricky bit :D
options: {
vus: 20,
duration: "30s",
},
},
"test2.js": {
type: "composite",
exec: "test2.js/default",
startAfter: "test1.js",
options: {
iterations: 1000,
vus: 20,
},
},
"test3.js": {
type: "composite",
exec: "test3.js/default",
startAfter: "test2.js",
options: {
execution: {
constant_arr_rate: {
type: "constant-arrival-rate",
rate: 20,
duration: "1m",
preAllocatedVUs: 10,
},
per_vu_iters: {
type: "per-vu-iterations",
vus: 10,
iterations: 100,
maxDuration: "1m"
},
},
},
},
}Notice how, with a few minor changes, we have a whole new layer of flexibility - test suites, for lack of a better term. All the wile, we're preserving the nice new properties of being able to tell precisely how many VUs our test suite will use at most (20 in this case) and what the max test suite duration will be, giving us predictability and easy billing.
And, as I mention in the code comment above, the tricky bit isn't actually the execution. It would actually be things like figuring out how to reference the different default functions in the config. I don't think it's a huge issue, but we should be careful how we structure the archive bundles and the related things.
Also, because of the super-global k6 configuration (the curse of #883 strikes again 🤦♂️ ), I'm not sure how we should handle non-execution options that are different between scripts. We can probably refactor that at a later point though. And things like the planned new HTTP API (issue TBD 😊 ) would greatly reduce the issue... Still, some refactoring is likely required, even for a MVP version of the "full test suites 100% version"...
So, yeah, this seems reasonable, after we release #1007:
- Add a small PR that implements
startAfter, cover (hopefully) 80% of use cases - Add a medium-sized PR that implements the
compositeexecutor. No support fork6 run script1.js script2.jsat this point, users have to manually configure the hierarchical config). Hopefully that covers 90% of use cases. - Figure out the tricky bits of implementing
k6 run script1.js script2.js. This will give us great UX and hopefully 100% coverage of use cases. We can do this step much, much later than steps 1 and 2. Probably smart to do it after we have the new HTTP API.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status