Generated Token every 10 mins and use it during load test

in my scenario, I want to generate a token and use it for 10 mins (validity ) Please help me to understand more about this logic, Where should we add this code, should we add this to generate token API or before using a token

my scenario looks like
import { group } from ‘k6’;
import {check , sleep} from ‘k6’;
import http from ‘k6/http’;
import { htmlReport } from “K6 Load Test: <%= title %>”;
import { textSummary } from ‘404 - resource not found
import { SharedArray } from “k6/data”;
import papaparse from “404 - resource not found;
import encoding from ‘k6/encoding’;
import { findBetween } from ‘404 - resource not found;

export const options = {

scenarios: {
setup: { // some arbitrary scenario name for genarate token
executor: ‘per-vu-iterations’,
vus: 1,
//duration: ‘1s’,
iterations: 2,
gracefulStop: ‘0s’, // do not wait for iterations to finish in the end
tags: { test_type: ‘setup’ }, // extra tags for the metrics generated by this scenario
exec: ‘setup’, // the function this scenario will execute
},
scenario1: { // some arbitrary scenario name
executor: ‘constant-vus’,
//executor: ‘per-vu-iterations’,
vus: 15,
duration: ‘60m’,
//iterations: 10,
gracefulStop: ‘0s’, // do not wait for iterations to finish in the end
tags: { test_type: ‘scenario1’ }, // extra tags for the metrics generated by this scenario
exec: ‘scenario1’, // the function this scenario will execute
},
scenario2: { // some arbitrary scenario name
executor: ‘constant-vus’,
//executor: ‘per-vu-iterations’,
vus: 15,
duration: ‘60m’,
//iterations: 10,
gracefulStop: ‘0s’, // do not wait for iterations to finish in the end
tags: { test_type: ‘scenario2’ }, // extra tags for the metrics generated by this scenario
exec: ‘scenario2’, // the function this scenario will execute
},

},
discardResponseBodies: false,
thresholds: {
// we can set different thresholds for the different scenarios because
// of the extra metric tags we set!
‘http_req_duration{test_type:api}’: [‘p(95)<250’, ‘p(99)<350’],
‘http_req_duration{test_type:website}’: [‘p(99)<500’],
http_req_duration: [{
threshold: ‘p(90) < 500’,
threshold: ‘p(95) < 900’,
abortOnFail: false,
}]

  // we can reference the scenario names as well
  //'http_req_duration{scenario:my_api_test_2}': ['p(99)<300'],

}

};

export function setup () { //genarating token here

var url1 = ‘token genaration url’;

const payload1 = {
[“client_id”]: “13246546”,
[“client_secret”]:“466464646”,

}
const params1 = {
headers : {
‘Content-Type’: ‘application/x-www-form-urlencoded’,
‘Accept’ : ‘application/json’,
},

  tags: {
     name: 'Oauth', // first request
   },

 };

var Response1 = http.post(url1, payload1, params1, check);

// console.log(Response1.body);
// console.log(Response1.status);
// console.log(Response1);

check(url1, {
'is Auth ': (r) => Response1.status === 200,

});

let securityToken = findBetween(Response1.body, ‘“token”:“’, ‘”,’);

return {securityToken};
//sleep(3600);

}

export default function (data) {
//console.log((data.securityToken));
let authToken = data.json(‘access_token’);
let securityToken = findBetween(Response1.body, ‘“token”:“’, ‘”,’);
let refreshToken = findBetween(Response1.body, ‘“token”:“’, ‘”,’);
console.log(refreshToken);

}

export function scenario1 (data) {

var url = ‘’;
const payload = ``;

const params = {
headers : {
‘Content-Type’ : ‘application/json’,
‘token = bearer token’ // using here

},

tags: {
   name: '231', // first request
 },

};

//console.log(payload);
const Response = http.post(url, payload, params, check);
//console.log(Response.body);
//console.log(Response.status);
//console.log(globalThis.vars [“vuAuthToken”]);
check(url, {
'123456 ': (r) => Response.status === 200,
});
sleep(0.8)
}
var refreshed = 0;

export function scenario2 (data) {
var diff = new Date() - refreshed
if (diff > 4999) {
console.log(refresh the token)
refreshed = new Date()
}
}
var url = ‘scenario2’;
const payload = ``;

const params = {
headers : {
‘Content-Type’ : ‘application/json’,
‘Authorization’: Bearer token, // token using here
},

tags: {
name: ‘1313gdgd’, // first request
},

};

//console.log(payload);
const Response = http.post(url, payload, params, check);
// console.log(Response.body);
// console.log(Response.status);
console.log(data.securityToken);

check(url, {
'134654 ': (r) => Response.status === 200,
});
sleep(0.8)
}

can anyone help me with this fix

Hi @Sreenivas

The recommendations in Periodically refreshing a token aside a script - #3 by codebien are valid for your case. Are you finding it difficult to introduce in your script?

I’ve tried to get the script from your initial message but it’s not easy. I had to replace characters (probably from the copy&paste if you are using Windows?), and some of the syntax is still not correct. It would help if you can provide a working script within block codes like below, but simplified and working, so I can reproduce your code:

import { group } from 'k6';
import { check, sleep } from 'k6';
import http from 'k6 / http';
import { htmlReport } from 'K6 Load Test: <%= title %>';
import { textSummary } from 'https://jslib.k6.io/k6-summary/0.0.1/index.js'
import { SharedArray } from 'k6 / data';
import papaparse from 'https://jslib.k6.io/papaparse/5.1.1/index.js';
import encoding from 'k6 / encoding';
import { findBetween } from 'https://jslib.k6.io/k6-utils/1.2.0/index.js';

export const options = {
    scenarios: {
        setup: { // some arbitrary scenario name for genarate token
            executor: 'per- vu - iterations',
            vus: 1,
            //duration: '1s',
            iterations: 2,
            gracefulStop: '0s', // do not wait for iterations to finish in the end
            tags: { test_type: 'setup' }, // extra tags for the metrics generated by this scenario
            exec: 'setup', // the function this scenario will execute
        },
        scenario1: { // some arbitrary scenario name
            executor: 'constant- vus',
            //executor: 'per-vu-iterations',
            vus: 15,
            duration: '60m',
            //iterations: 10,
            gracefulStop: '0s', // do not wait for iterations to finish in the end
            tags: { test_type: 'scenario1' }, // extra tags for the metrics generated by this scenario
            exec: 'scenario1', // the function this scenario will execute
        },
        scenario2: { // some arbitrary scenario name
            executor: 'constant- vus',
            //executor: 'per-vu-iterations',
            vus: 15,
            duration: '60m',
            //iterations: 10,
            gracefulStop: '0s', // do not wait for iterations to finish in the end
            tags: { test_type: 'scenario2' }, // extra tags for the metrics generated by this scenario
            exec: 'scenario2', // the function this scenario will execute
        },

    },
    discardResponseBodies: false,
    thresholds: {
        // we can set different thresholds for the different scenarios because
        // of the extra metric tags we set!
        'http_req_duration{ test_type: api }': ['p(95) < 250', 'p(99) < 350'],
        'http_req_duration{ test_type: website }': ['p(99) < 500'],
        http_req_duration: [{
            threshold: 'p(90) < 500',
            threshold: 'p(95) < 900',
            abortOnFail: false,
        }]

        // we can reference the scenario names as well
        //'http_req_duration{scenario:my_api_test_2}': ['p(99)<300'],

    }

};

export function setup() { //genarating token here

    var url1 = 'token genaration url';

    const payload1 = {
        [“client_id”]: “13246546”,
        [“client_secret”]:“466464646”,

    }
    const params1 = {
        headers: {
            'Content - Type': 'application / x - www - form - urlencoded',
            'Accept': 'application / json',
        },

        tags: {
            name: 'Oauth', // first request
        },

    };

    var Response1 = http.post(url1, payload1, params1, check);

    // console.log(Response1.body);
    // console.log(Response1.status);
    // console.log(Response1);

    check(url1, {
        'is Auth ': (r) => Response1.status === 200,

    });

    let securityToken = findBetween(Response1.body, '“token”:“', '”,');

    return { securityToken };
    //sleep(3600);

}

export default function (data) {
    //console.log((data.securityToken));
    let authToken = data.json('access_token');
    let securityToken = findBetween(Response1.body, '“token”:“', '”,');
    let refreshToken = findBetween(Response1.body, '“token”:“', '”,');
    console.log(refreshToken);

}

export function scenario1(data) {

    var url = '';
    const payload = '';

    const params = {
        headers: {
            'Content - Type': 'application / json',
            'token': 'bearer token' // using here

        },

        tags: {
            name: '231', // first request
        },

    };

    //console.log(payload);
    const Response = http.post(url, payload, params, check);
    //console.log(Response.body);
    //console.log(Response.status);
    //console.log(globalThis.vars [“vuAuthToken”]);
    check(url, {
        '123456': (r) => Response.status === 200,
    });
    sleep(0.8)
}

var refreshed = 0;

export function scenario2(data) {
    var diff = new Date() - refreshed
    if (diff > 4999) {
        console.log(refresh the token)
        refreshed = new Date()
    }
    var url = 'scenario2';
    const payload = ``;

    const params = {
        headers: {
            'Content - Type': 'application / json',
            'Authorization': Bearer token, // token using here
        },

        tags: {
            name: '1313gdgd', // first request
        },

    };

    //console.log(payload);
    const Response = http.post(url, payload, params, check);
    // console.log(Response.body);
    // console.log(Response.status);
    console.log(data.securityToken);

    check(url, {
        '134654': (r) => Response.status === 200,
    });
    sleep(0.8)
}

Also a bit more context will help. I’m not familiar with the system you’re testing and interacting with. It would be really tricky to give you a satisfying answer without getting more information from you.

I see that you are creating the initial token in the setup() function which is also an scenario? You might want to have a look at the test lifecycle. This will share the token with all VUs, but after 10 minutes each VU will generate a new token. Will that work for your system?

You also have a mix of scenarios and the default() function. I would initially simplify that, work on the token refresh and then reintroduce the complexity. Once your token refresh strategy is working.

To summarize, it will help if you provide more context about your system and what you want to achieve, and to provide a simplified test that we can execute, so we can suggest a concrete alternative.

Cheers!

Thank you @eyeveebe for your support
My scenario :

  • step 1: HTTP request //generate token here and use this token for next request , but this token is valid for 10mins only
  • step 2: http request and using token (generated in step1) in headers , this step I want do it for longer duration like 1 hour or 3hours , but after 10 mins test getting failed due invalid token. In step2 I want to use new token after every 10mins

How this is possible in K6 , can we try with while loop execute step2 10mins and exit , generate token and run step 2 or any possibility

I see below code from Periodically refreshing a token aside a script, how to use this in my scenario

var refreshed = 0;

export default function() {
	var diff = new Date() - refreshed 
	if (diff > 4999) {
		console.log(`refresh the token`)
		refreshed = new Date()
	}
}

My sample k6 script

import { group } from 'k6';
import {check , sleep} from 'k6';
import http from 'k6/http';

const OauthURL = 'https://test.com/token';
//console.log(OauthURL);
  
export default function () {

  var url1 = OauthURL; //generate token
        const payload1 = {
              ["client_id"]: "test",
              ["client_secret"]:"test",
              
}

const params1 = {
           headers : {
            'Content-Type':  'application/x-www-form-urlencoded',
            },

             tags: {
                name: 'Oauth', // first request
              },

            };
                    
     const Response1 =  http.post(url1, payload1, params1, check);
      
      check(url1, {
       'is Auth ': (r) => Response1.status === 200,
       
    });
    sleep(5)
    let vuAuthToken = Response1.json('access_token');
            //console.log(vuAuthToken);


        var url = 'https://test.com/source';
        const payload = `{Json Payload here}`;

const params = {
           headers : {
            'Content-Type'  : 'application/json',
            'Authorization': `Bearer ${vuAuthToken}`,//expires in 10mins
            },

             tags: {
                name: 'test', // first request
              },

            };
          
     
     const Response =  http.post(url, payload, params, check);
     
      check(url, {
       'is test ': (r) => Response.status === 200,
       
    });
    sleep(1)
    
    
}

Hi @eyeveebe , it would be great any solution to resolve this issue.

Hi @Sreenivas

I believe a combination of Unique login for each virtual User - #11 by immavalls2 and the aforementioned Periodically refreshing a token aside a script - #3 by codebien can help here.

In the VU stage (default function), check if the last token refresh was 10 minutes ago, and generate a new token. You can separate the code to get a new token into another function to make it cleaner.

Based on the last piece of code you shared, I would refactor it a bit into something similar to:

import { check, sleep } from 'k6';
import http from 'k6/http';

const OauthURL = 'https://test.com/token';
let refreshed = 0;
let vuAuthToken;

export function getToken(client_id, client_secret) {
    var url1 = OauthURL; //generate token
    const payload1 = {
        ["client_id"]: client_id,
        ["client_secret"]: client_secret,
    }

    const params1 = {
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
        },
        tags: {
            name: 'Oauth', // first request
        },
    };
    const Response1 = http.post(url1, payload1, params1, check);
    check(url1, {
        'is Auth ': (r) => Response1.status === 200,

    });
    sleep(5); // do you need to sleep here?
    return Response1.json('access_token');
}

export default function () {
    var diff = new Date() - refreshed;
    if (diff > 9999) {
        console.log(`refresh the token`);
        vuAuthToken = getToken("test", "test");
        refreshed = new Date();
    }
    var url = 'https://test.com/source';
    const payload = `{Json Payload here}`;
    const params = {
        headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${vuAuthToken}`,//expires in 10mins
        },

        tags: {
            name: 'test', // first request
        },

    };
    const Response = http.post(url, payload, params, check);
    check(url, {
        'is test ': (r) => Response.status === 200,
    });
    sleep(1);
}

I hope this helps.

Cheers!

Thank you @eyeveebe , I will try this

1 Like

Hey @eyeveebe, I appreciate your lengthy answers in a number of these threads. I can see the Periodically refreshing a token aside a script - #3 by codebien approach by @codebien mentioned a few times as being the best approach.

However, I have tried this and the refreshed variable never gets reassigned, seemingly because it is deemed init code. Is my thinking correct here?

Hi @ruairiquinn

Thanks for the feedback, much appreciated.

I created a script to see if the refreshed value was updated, which it is, in my case.

import { check, sleep } from 'k6';

let refreshed = 0;

export const options = {
    vus: 1,
    duration: '10s',
};

export default function () {
    console.log("refreshed value:", refreshed);
    var diff = new Date() - refreshed;
    if (diff > 2000) {
        console.log(`refresh the token`);
        refreshed = new Date();
    } else {
        console.log(`do not refresh the token`);
    }
    sleep(1);
}

When running this, we can see that every 2 seconds, it will update the refreshed value.

INFO[0000] refreshed value: 0                            source=console
INFO[0000] refresh the token                             source=console
INFO[0001] refreshed value: "2023-10-08T20:13:40.228Z"   source=console
INFO[0001] do not refresh the token                      source=console
INFO[0002] refreshed value: "2023-10-08T20:13:40.228Z"   source=console
INFO[0002] refresh the token                             source=console
INFO[0003] refreshed value: "2023-10-08T20:13:42.230Z"   source=console
INFO[0003] do not refresh the token                      source=console
INFO[0004] refreshed value: "2023-10-08T20:13:42.230Z"   source=console
INFO[0004] refresh the token                             source=console
INFO[0005] refreshed value: "2023-10-08T20:13:44.231Z"   source=console
INFO[0005] do not refresh the token                      source=console
INFO[0006] refreshed value: "2023-10-08T20:13:44.231Z"   source=console
INFO[0006] refresh the token                             source=console
INFO[0007] refreshed value: "2023-10-08T20:13:46.233Z"   source=console
INFO[0007] do not refresh the token                      source=console
INFO[0008] refreshed value: "2023-10-08T20:13:46.233Z"   source=console
INFO[0008] refresh the token                             source=console
INFO[0009] refreshed value: "2023-10-08T20:13:48.235Z"   source=console
INFO[0009] do not refresh the token                      source=console

If you can share your (sanitized) script, we might be able to help spot why it’s not working in your concrete case.

Cheers!

Thanks for the example and the response @eyeveebee, I can confirm the refreshed variable does acually get updated within the default function.

In the example you used above with the vuAuthToken, say we had 30 VUs running, each one of those has a different reference to vuAuthToken. So, we end up with 30 separate auth tokens per refresh period, when ideally we’d like to reuse one? Is there any way you can think of to work around this issue?

I tried this in a different executor “constant-arrival-rate” and it didn’t work here is my current script. It also doesnt work if I remove the exec and use a default function too.

I did run your test and it worked just fine though. Maybe its something with the different test executors.

import { check, sleep } from 'k6';

let refreshed = 0;

export const options = {
    scenarios: {
        create: {
        executor: 'constant-arrival-rate',
        duration: `10s`,
        rate: 1,
        preAllocatedVUs: 100,
        timeUnit: '1s',
        exec: 'create',
    }
}

};

export function create () {
    console.log("refreshed value:", refreshed);
    var diff = new Date() - refreshed;
    if (diff > 2000) {
        console.log(`refresh the token`);
        refreshed = new Date();
    } else {
        console.log(`do not refresh the token`);
    }
    sleep(1);
}

output

k6 run .\refresh.js

          /\      |‾‾| /‾‾/   /‾‾/
     /\  /  \     |  |/  /   /  /
    /  \/    \    |     (   /   ‾‾\
   /          \   |  |\  \ |  (‾)  |
  / __________ \  |__| \__\ \_____/ .io

  execution: local
     script: .\refresh.js
     output: -

  scenarios: (100.00%) 1 scenario, 100 max VUs, 40s max duration (incl. graceful stop):
           * create: 1.00 iterations/s for 10s (maxVUs: 100, exec: create, gracefulStop: 30s)

INFO[0000] refreshed value: 0                            source=console
INFO[0000] refresh the token                             source=console
INFO[0001] refreshed value: 0                            source=console
INFO[0001] refresh the token                             source=console
INFO[0002] refreshed value: 0                            source=console
INFO[0002] refresh the token                             source=console
INFO[0003] refreshed value: 0                            source=console
INFO[0003] refresh the token                             source=console
INFO[0004] refreshed value: 0                            source=console
INFO[0004] refresh the token                             source=console
INFO[0005] refreshed value: 0                            source=console
INFO[0005] refresh the token                             source=console
INFO[0006] refreshed value: 0                            source=console
INFO[0006] refresh the token                             source=console
INFO[0007] refreshed value: 0                            source=console
INFO[0007] refresh the token                             source=console
INFO[0008] refreshed value: 0                            source=console
INFO[0008] refresh the token                             source=console
INFO[0009] refreshed value: 0                            source=console
INFO[0009] refresh the token                             source=console
INFO[0010] refreshed value: 0                            source=console
INFO[0010] refresh the token                             source=console

     data_received........: 0 B 0 B/s
     data_sent............: 0 B 0 B/s
     iteration_duration...: avg=1s min=1s med=1s max=1.01s p(90)=1.01s p(95)=1.01s
     iterations...........: 11  0.998609/s
     vus..................: 1   min=0      max=2
     vus_max..............: 100 min=100    max=100


running (11.0s), 000/100 VUs, 11 complete and 0 interrupted iterations
create ✓ [======================================] 000/100 VUs  10s  1.00 iters/s

Hi @frankwayne, welcome to the community forum!

It is because @eyeveebee’s example was running on 1 VU and yours is running on 100. The refreshed variable is not shared among VUs, so every VU is started with refreshed = 0

Actually, if you move the console.log("refreshed value:", refreshed); line right above the sleep(1) you will see, that every VU in its every first iteration refreshed the value.

Thanks for the reply @bandorko but doesnt this end metric

     vus..................: 1   min=0      max=2

show that only two VUs were created and ran. the vus_max is just the max number possible.
I updated the script to test this out and the same result happened

import { check, sleep } from 'k6';
import {setTimeout} from 'k6/experimental/timers'

let refreshed = 0;

export const options = {
    scenarios: {
        create: {
        executor: 'constant-arrival-rate',
        duration: `10s`,
        rate: 1,
        preAllocatedVUs: 2,
        timeUnit: '1s',
    }
}

};

let counter = 0;
// setTimeout( () => {
//     counter++;
// }, 3000)

export function setup() {
    return 1;    
}

let token = null;
export default function (data) {
    if(token == null) {
        console.log(`updating token`);
        token = `aa`;
    }
    console.log(`data: ${data}`);
    console.log(`counter: ${counter}`);
    data++;
    sleep(1);
    return data;
}

output

 k6 run .\refresh.js

          /\      |‾‾| /‾‾/   /‾‾/
     /\  /  \     |  |/  /   /  /
    /  \/    \    |     (   /   ‾‾\
   /          \   |  |\  \ |  (‾)  |
  / __________ \  |__| \__\ \_____/ .io

  execution: local
     script: .\refresh.js
     output: -

  scenarios: (100.00%) 1 scenario, 2 max VUs, 40s max duration (incl. graceful stop):
           * create: 1.00 iterations/s for 10s (maxVUs: 2, gracefulStop: 30s)

INFO[0000] updating token                                source=console
INFO[0000] data: 1                                       source=console
INFO[0000] counter: 0                                    source=console
INFO[0001] updating token                                source=console
INFO[0001] data: 1                                       source=console
INFO[0001] counter: 0                                    source=console
INFO[0002] data: 1                                       source=console
INFO[0002] counter: 0                                    source=console
INFO[0003] data: 1                                       source=console
INFO[0003] counter: 0                                    source=console
INFO[0004] data: 1                                       source=console
INFO[0004] counter: 0                                    source=console
INFO[0005] data: 1                                       source=console
INFO[0005] counter: 0                                    source=console
INFO[0006] data: 1                                       source=console
INFO[0006] counter: 0                                    source=console
INFO[0007] data: 1                                       source=console
INFO[0007] counter: 0                                    source=console
INFO[0008] data: 1                                       source=console
INFO[0008] counter: 0                                    source=console
INFO[0009] data: 1                                       source=console
INFO[0009] counter: 0                                    source=console
INFO[0010] data: 1                                       source=console
INFO[0010] counter: 0                                    source=console

     █ setup

     data_received........: 0 B 0 B/s
     data_sent............: 0 B 0 B/s
     iteration_duration...: avg=922.91ms min=0s med=1s max=1.01s p(90)=1.01s p(95)=1.01s
     iterations...........: 11  0.998858/s
     vus..................: 2   min=0      max=2
     vus_max..............: 2   min=2      max=2


running (11.0s), 0/2 VUs, 11 complete and 0 interrupted iterations
create ✓ [======================================] 0/2 VUs  10s  1.00 iters/s

@frankwayne
In your previous comment there were preAllocatedVUs: 100. Now it is 2

Is the number beside the info logging the VU id ?

INFO[0000]
INFO[0007]

I also see that my test code for a token update only got ran once per VU, but strangely though the int value is not getting updated.

@bandorko yes I updated the script to a lower VU count to see what is happening in the second post

well… updating the value may help…

Thanks @bandorko

I commented your code

let counter = 0;     // both VU starts with counter=0
// setTimeout( () => {
//     counter++;
// }, 3000)


export function setup() {     //setup function runs once
    return 1;    // this value will be set in the default() in every iteration 
}

let token = null;
export default function (data) {    // data is 1 in every iteration
    if(token == null) {   // in the first iteration in both VU this condition is true
        console.log(`updating token`); 
        token = `aa`;
    }
    console.log(`data: ${data}`);   // data is 1 in every iteration
    console.log(`counter: ${counter}`);  // counter is 0 in every iteration because you never increment it
    data++;  // you can't modify data this way
    sleep(1);
    return data;  // this is meaningless k6 will not use it
}
1 Like

No. I think it is the iteration id