k6

Logging out users in teardown during k6 test


I have a K6 performance test which runs with multiple virtual users and logs in a application user during the test.

Once the test is complete, I want to call our application to logout the users.

At first I thought I could use a SharedArray to gather a list of the users to later logout in teardown, however I've confirmed SharedArray is immutable.

Other suggestions I've seen are to have the virtual users write out to an external system like a database to store which users got accessed. However I believe this will add a lot of latency by writing to the DB.

How can get the list of user ids from my application who had the test run on in the K6 teardown?

I’ve tried adding the http application logins to the setup function, but it seems on the second request it has a problem possibly related to cookies. How can I setup the cookies in the setup properly?


Solution

  • You can perform the login for all users in the setup() function, collect all cookies and then pass them to the default test function.

    export function setup() {
      const cookies = [];
      for (let i = 0; i < number_of_users; ++i) {
        const jar = new http.CookieJar();
        const res = http.post(
          ...,
          JSON.stringify({username:..., password:...}),
          { jar });
    
        cookies[i] = jar.cookiesForURL(res.url);
      }
      return { cookies };
    }
    

    You can either compute/generate the usernames and passwords based on the user number or use a JSON file that you read into a SharedArray in your init context.

    This allows you to extract and set the user-specific cookie in your test function per VU:

    export default function(data) {
      const cookies = data.cookies;
      const cookie = cookies[__VU % number_of_users]; // get cookie for user
    
      http.cookieJar().set(your_domain, cookie_name, cookie[cookie_name]);
    
      http.get(...); // uses the cookies that were set in the line above
    }
    

    Eventually, you want to log out the users again:

    export function teardown(data) {
      for (let cookie of data.cookies) {
        http.post(..., { cookies: {
          cookie_name: cookie[cookie_name]
        } });
      }
    }
    

    You can also import the k6/execution module which provides access to a unique VU id and use that instead of the global __VU.

    I have used such an approach with great success in several projects.

    Alternatively, it is possible to log in each VU in the first iteration (without a setup function):

    import exec from 'k6/execution';
    
    export default function() {
      if (exec.vu.iterationInInstance == 0) {
        // perform login
        return;
      }
    
      // here your actual load test code
    }
    

    Additional resources: