简体   繁体   中英

remove ids generated during the tests

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?

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

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:

  1. Start a Webdis/Redis container: docker run --rm -it -p 127.0.0.1:7379:7379 nicolas/webdis

  2. 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');
}
  1. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM