Share data between two scenarios in K6

I am running two functions (funcA and funcB ) using scenarios. I would like to share data between them.

step 1 - FuncA will run with different environment variables

step 2 - FuncB will run after few seconds getting some data from funcA and with different environment variables

export let options = {
  scenarios: {
    funcA: {
      exec: "funcA",
      executor: "per-vu-iterations",
     env: { id: 'funcA' },
    },
    funcB: {
      exec: "funcB",
      startTime: '30s',
      executor: "per-vu-iterations",
     env: { id: 'funcB' },
    },
  },
  thresholds: {
    failedTestCases: [{ threshold: "count===0", abortOnFail: false }],
  },
};

export function funcA() {
  runA();
}

export function funcB() {
 runB();
}

I know there is an sharedArray to share data between two virtual users but that’s read only. Could you describe some options to share data between two scenarios. We run around 300 functional tests using k6 and there are some scripts which we would like to run with different set of environment variables. I can see scenarios is an option for us.

Hi @rakeshsukla53,

There is no way to share a writable state between VUs. This is unlikely to change soon as there conceptual problems with distributed execution that will need to be fixed IMO before we even try it.

Depending on you use case you can:

  1. use an HTTP server/application to save what you want from the end of funcA and get it at the beginning of funcB - this is by far the most future proof solution, but requires an external tool
  2. you can write your own xk6 extension as long as you won’t run in the cloud. I have shown how to do it with an ever-increasing counter - you can do something more with that if you want to. This is also fairly future proof, but also requires some coding in golang and using xk6 which means it won’t work in the cloud
  3. VUs are reused between scenarios if possible which means that if you fiddle enough with the times and gracefulRampDowns/gracefulShutdowns you can have the same VUs executing both funcA and funcB. At which point you can use their global scope to share state. This probably is the “easiest” solution, but have the limitation that you need to have the same number of VUs and if you at any point change any of the numbers in one scenario - you will need to touch the others. Also while unlikely there is none zero chance that k6 in the future might decide not to work like that, this is after all an implementation detail, even if one that we tried and made happen.
    A good example is shown in this comment that shows how to have a per VU setup and teardown like phase, with the caveats explained above.
  4. depending on what you exactly want to do it is very possible that you can forgo the whole scenarios and just have 1 VU that does them all … even in a single iteration. This of course depends on what you mean by “functional tests”

Hope this helps you, also look at this comment about httpx which is now having some documentation being added, it might be useful for your functional tests.

Hello.
My need is very similar.
I need to loadtest an API endpoint which supposes to receive an exact parameter value (otherwise it won’t do all the work I have to test). I have a large list of those values. The problem is that each value can be used only once.
So I need to share that list with all running VUs (which is for sure possible with SharedArray), and somehow make VUs take each value only once (which doesn’t seem possible).
Yes, I know SharedArray is r/o. But why is it so? I’m not a js programmer, but I know, other languages have r/w IPC means (like lists with a ‘pop’ method, or queues), which allow to take one item only once.
Thank you

Hi @tier, welcome to the forum.

I will argue (as I have argued before) that you basically need a counter going up so you can get the next id in the shared array, which is what xk6-counter does perfectly fine.

And as @ned has explained here and in this issue this can be done if we give access to the global iteration counter of a shared-iterations executor. Also arguably data segmenation is exactly what this about, just that in this case, a simple counter is all that is needed.