How to identify if a Vuser has finished an iteration when using data parameterization

I have a CSV file of user emails, which I use to login to the system. I am aware with the latest version of K6 now we can use exec.scenario.iterationInTest to get a unique value across Vus to pick data from the file. While using this I am facing the below concern and my test configuration is as below

scenarios: {
    scenario_one: {
      executor: 'shared-iterations',
      exec: 'myFunction',
      vus: 2,
      iterations: 4,
    }
}

users_file.csv

  1. user_A@test.com
  2. user_B@test.com

I’m using below code snippet to pick my users from the csv file.

  let iterationInTest = exec.scenario.iterationInTest;
  let index = iterationInTest % dataFile.length;
  const user = JSON.stringify(dataFile[index].email);

When the execution function is run again to complete the 2nd set of iterations, how can I know which user has completed the previous iteration and which user has not or might not have finished the iteration? Because, using an already logged in user would result the old session to be invalidated and result in failures of any ongoing tests from prev. iteration.

I am pretty new to K6 and any help in resolving/understanding this is much appreciated. Thanks!

Hi @shamikam

Sorry for the late reply! What do you think about using constant-vus instead? (constant-vus docs) It sounds to me as if there’s a limited number of users that you can use for a login at a time (2 in your example) and if so, it might be best to try to limit number of VUs. With constant-vus executor, you can set number of VUs equal to the number of available users and designate each VU with specific user:

scenarios: {
  scenario_one: {
    executor: 'constant-vus',
    vus: 2, // <-- number of users in CSV
    duration: '5m',
  }
}
...
let vuId = exec.vu.idInInstance;
const user = JSON.stringify(dataFile[vuId].email);

With this, there should be no overlaps in when users from CSV are logging in and you’ll get as many iterations as possible with the given time frame.

Thanks for the reply. That does resolve my original problem.
But the initial reason I went with scenario.iterationInTest is to get a unqiue value across multiple scenarios. In order to simply my question I didn’t include that this test involves multiple scenarios. Sorry about that. So with multiple scenarios, exec.vu.idInInstance can give me a vuId that is out side the length of the CSV file.

Hmm, I’m not sure I fully follow: exec.vu.idInInstance is unique in the instance so unique across scenarios too. Are you saying that number of VUs is greater than the number of users that can log in at the same time? But what are these VUs for? If they shouldn’t login, they’d be stuck and thus useless for the test run, right?

Even if there are multiple scenarios, it’s possible to estimate and / or limit a total number of VUs in the test run. If there is a point when number of VUs gets greater than users in CSV, then probably the setup of the test must be changed or perhaps, a workaround found. So the options that could be tried:

  1. change the setup. If you’re using something like constant-arrival-rate then there is a maxVUs to limit number of total VUs.
  2. if the setup cannot be changed (why?), workarounds. E.g. is it necessary for each iteration to login in the first place, can the login info be shared, etc.
  3. in the worst case, you probably could create a global object to track which users are currently “free” and make iteration sleep and wait until there is a free user but it definitely makes sense to first try to resolve this problem at the setup level.

Let me elaborate the setup of both my scenarios.

scenarios: {
  scenario_one: {
      executor: 'shared-iterations',
      exec: 'myFunctionOne',
      vus: 2,
      iterations: 4,
    }

scenario_two: {
      executor: 'shared-iterations',
      exec: 'myFunctionTwo',
      vus: 2,
      iterations: 4,
    }
}

scenario_one - will pick up username to login from CSV file 1
scenario_two - will pick up username to login from CSV file 2.

These are two different user role types in the SUT.

So according to my understanding this will spawn up 4 virtual users to execute both the scenarios. And each VU will have a vu.idInstance starting from 0 and leading up to 3. If scenario_one gets assigned VU=2 and VU=3, with below code it won’t return me a correct user as there are no users matching 2 and 3 indexes in CSV file.

let vuId = exec.vu.idInInstance;
const user = JSON.stringify(dataFile[vuId].email);

So to answer to your suggestions:

  1. I think this might work with maxVUs. Thanks I will try that out.
  2. Just out of curiosity, how can I share the login information between iterations? My understanding was that each iteration will start fresh and initialize all variables again and any information from previous iterations will be lost.

how can I share the login information between iterations? My understanding was that each iteration will start fresh and initialize all variables again and any information from previous iterations will be lost.

There is definitely some info shared :slightly_smiling_face: Please see about the test life cycle: it describes init code which is executed before anything else and setup and teardown functions that are run before and after the test run. So it is possible to define variables in init code and / or setup and then share them between iterations.

this will spawn up 4 virtual users to execute both the scenarios.

Yes, you’re right, this configuration will spawn 4 VUs but my question was why spawn 4 VUs if only 2 can do meaningful work at one point of time? I.e. what the other two VUs are supposed to do? For example, if one of the scenarios is finished much earlier than the second one, then it might make sense to add a third scenario which will start after the first one and so on. (option startTime in scenarios docs)
But perhaps, using setup and init will be preferable to tinkering with scenarios.