Is it possible to run in parallel visits of different site paths for different VUs?

We have a server that serves bunch of different sites. From our backend I receive an array of sites we want to load test. The meta data for each site looks like this:

{
  domain: "https://site-a.com",
  pages: [
    "/page-1",
    "/page-2",
  ],
}

The goal of testing is to recreate as close as possible the real-world scenario when different users visit different sites: N sites at the same time, but not all of them and not sequentially one after another.
The initial plan was to take first N sites from the received array of sites and run in parallel as group of M users visit each page from an array of pages for each site. When this chunk of tests finished, take next N sites and repeat until all sites are tested. I was looking into the docs and as a result I’m not sure if it’s possible to implement such tests with k6. I’d be happy to be proved wrong :slight_smile:

Appreciate suggestions and thanks in advance!

I am not sure I completely understand your requirements, but maybe something like this would satisfy your use case?

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

let sitesToTest = [
    {
        domain: 'https://test.k6.io',
        pages: [
            '/contacts.php?t=1',
            '/news.php?t=1',
            '/pi.php?decimals=1',
            '/contacts.php?t=2',
            '/news.php?t=2',
            '/pi.php?decimals=2',
        ],
    },
    {
        domain: 'https://test-api.k6.io',
        pages: [
            '/public/crocodiles/',
            '/public/crocodiles/1/',
            '/public/crocodiles/2/',
            '/public/crocodiles/3/',
        ],
    },
    {
        domain: 'https://httpbin.test.k6.io',
        pages: [
            '/get',
            '/anything?foo=bar',
        ],
    },
    {
        domain: 'https://test.k6.io',
        pages: [
            '/contacts.php?t=3',
            '/news.php?t=3',
            '/pi.php?decimals=3',
            '/contacts.php?t=4',
            '/news.php?t=4',
            '/pi.php?decimals=4',
            '/contacts.php?t=5',
            '/news.php?t=5',
            '/pi.php?decimals=5',
        ],
    },
    {
        domain: 'https://httpbin.test.k6.io',
        pages: [
            '/',
            '/anything?bar=baz',
        ],
    },
]

const vus = 2;

export const options = {
    scenarios: {
        contacts: {
            executor: 'per-vu-iterations',
            vus: vus,
            iterations: Math.ceil(sitesToTest.length / vus),
            maxDuration: '10m',
        },
    },
};

export default function () {
    var siteID = vus * (__VU - 1) + __ITER; // __VU starts from 1, __ITER from 0...
    if (siteID >= sitesToTest.length) {
        return; // this VU ran out of work
    }
    var site = sitesToTest[siteID];
    console.log(`VU=${__VU}, ITER=${__ITER} is testing site ${site.domain}...`);

    site.pages.forEach(path => {
        var url = site.domain + path;
        console.log(`   VU=${__VU}, ITER=${__ITER} is getting ${url}`);
        http.get(url);
        sleep(1);
    });
}

This will be even easier once we have Improve execution information in scripts · Issue #1320 · grafana/k6 · GitHub, there would be no need to use per-vu-iterations and the “this VU ran out of work” hack, but this should work.

Thanks for the example! It’s not 100% what I need but it cleared up a few things for me so I was able to implement what I had in mind. Cheers!