问题
For load testing in the vu
stage I generate a lot of objects with unique ids that I put them in the database. I want to delete them during teardown
stage in order not to pollute the database.
When keeping the state like this
let ids = [];
export function setup() {
ids.push('put in setup id');
}
export default function () {
ids.push('put in vu id');
}
export function teardown() {
ids.push('put in teardown id');
console.log('Resources: ' + ids);
}
it doesn't work as the array always contains the data I put in teardown
stage.
Passing data between stages also doesn't work due to well-know Cannot extend Go slice
issue, but even with that, you cannot pass the data from vu
stage to teardown
as it always gets the data from setup
stage.
The only remaining solution is either playing around with console log
or just use a plain preset of ids and use them in tests. Is there another way?
回答1:
The setup()
, teardown()
, and the VUs' default
functions are executed in completely different JavaScript runtimes. For distributed execution, they may be executed on completely different machines. So you can't just have a global ids
variable that you're able to access from everywhere.
That limitation is the reason why you're supposed to return any data you care about from setup()
- k6 will copy it and pass it as a parameter to the default
function (so you can use whatever resources you set up) and teardown()
(so you can clean them up).
Your example has to look somewhat like this:
export function setup() {
let ids = [];
ids.push('put in setup id');
return ids;
}
export default function (ids) {
// you cannot push to ids here
console.log('Resources: ' + ids);
}
export function teardown(ids) {
console.log('Resources: ' + ids);
}
You can find more information at https://k6.io/docs/using-k6/test-life-cycle
回答2:
To expand on @na--'s answer, I propose an external workaround using Redis and Webdis to manage the IDs.
It's actually quite simple, if you don't mind running an additional process, and shouldn't impact performance greatly:
Start a Webdis/Redis container:
docker run --rm -it -p 127.0.0.1:7379:7379 nicolas/webdis
script.js
:
import http from 'k6/http';
const url = "http://127.0.0.1:7379/"
export function setup() {
const ids = [1, 2, 3];
for (let id of ids) {
http.post(url, `LPUSH/ids/${id}`);
}
}
export default function () {
const id = Math.floor(Math.random() * 10);
http.post(url, `LPUSH/ids/${id}`);
}
export function teardown() {
let res = http.get(`${url}LRANGE/ids/0/-1`);
let ids = JSON.parse(res.body)['LRANGE'];
for (let id of ids) {
console.log(id);
}
// cleanup
http.post(url, 'DEL/ids');
}
- Run 5 iterations with:
k6 run -i 5 script.js
Example output:
INFO[0000] 7
INFO[0000] 2
INFO[0000] 2
INFO[0000] 6
INFO[0000] 5
INFO[0000] 3
INFO[0000] 2
INFO[0000] 1
A drawback of this solution is that it will skew the overall test results, because of the additional HTTP requests that are not relevant to the test itself. There might be a way to exclude these with tags, otherwise it would be a good feature request. :)
Using a Node.js Redis client to avoid HTTP requests could be an alternative, but those libraries usually aren't "browserifiable" so they likely wouldn't work in k6.
来源:https://stackoverflow.com/questions/60570067/remove-ids-generated-during-the-tests