[Feature]: Concurrent execution of the tests required
🚀 Feature Request
When executing tests, one is unable to run the tests concurrently.
The concurrent execution is tightly coupled with workers, which need not be the case.
We need to execute 100s of backend tests (Not UI based) that sends a message, wait few seconds, then check the response in DB for example. We cannot have 100s of workers, and we also have to wait "sequentially" since the concurrency is currently tied with workers.
Example
The below code should execute in 3 seconds even if the number of workers is 1, but it is currently taking 9 seconds.
import { test } from '@playwright/test';
test.describe.configure({ mode: 'parallel' });
const delay = (ms: number) => new Promise(r => setTimeout(r, ms));
test('test A - 3s delay', async () => {
const start = Date.now();
console.log('A started at', new Date().toISOString());
await delay(3000);
console.log('A ended after', (Date.now() - start) / 1000, 'seconds');
});
test('test B - 3s delay', async () => {
const start = Date.now();
console.log('B started at', new Date().toISOString());
await delay(3000);
console.log('B ended after', (Date.now() - start) / 1000, 'seconds');
});
test('test C - 3s delay', async () => {
const start = Date.now();
console.log('C started at', new Date().toISOString());
await delay(3000);
console.log('C ended after', (Date.now() - start) / 1000, 'seconds');
});
Output:
Running 3 tests using 1 worker
A started at 2025-11-05T09:26:50.618Z
A ended after 3.002 seconds
✓ 1 [api] › tests/parallel.spec.ts:7:5 › test A - 3s delay (3.0s)
B started at 2025-11-05T09:26:53.636Z
B ended after 3.001 seconds
✓ 2 [api] › tests/parallel.spec.ts:14:5 › test B - 3s delay (3.0s)
C started at 2025-11-05T09:26:56.651Z
C ended after 3.002 seconds
✓ 3 [api] › tests/parallel.spec.ts:21:5 › test C - 3s delay (3.0s)
3 passed (9.7s)
Motivation
Enterprises are adopting "playwright" as the defacto standard for automation testing. But the backend testing needs such improvements for large organizations to adopt this better.
Frameworks like vitest already support this feature, example:
import { test, expect } from 'vitest';
const delay = (ms: number) => new Promise(r => setTimeout(r, ms));
test.concurrent('test A - 3s delay', async () => {
const start = Date.now();
console.log('A started at', new Date().toISOString());
await delay(3000);
console.log('A ended after', (Date.now() - start) / 1000, 'seconds');
expect(true).toBe(true);
});
test.concurrent('test B - 3s delay', async () => {
const start = Date.now();
console.log('B started at', new Date().toISOString());
await delay(3000);
console.log('B ended after', (Date.now() - start) / 1000, 'seconds');
expect(true).toBe(true);
});
test.concurrent('test C - 3s delay', async () => {
const start = Date.now();
console.log('C started at', new Date().toISOString());
await delay(3000);
console.log('C ended after', (Date.now() - start) / 1000, 'seconds');
expect(true).toBe(true);
});
vitest.config.ts:
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
pool: 'threads',
maxThreads: 1,
minThreads: 1,
},
});
Output from vitest
❯ npx vitest run
RUN v4.0.7 /Users/ramakrs7/work/vitest
stdout | parallel.test.ts > test C - 3s delay
A started at 2025-11-05T09:29:03.228Z
B started at 2025-11-05T09:29:03.228Z
C started at 2025-11-05T09:29:03.228Z
stdout | parallel.test.ts > test C - 3s delay
A ended after 3.002 seconds
stdout | parallel.test.ts
B ended after 3.006 seconds
stdout | parallel.test.ts
C ended after 3.007 seconds
✓ parallel.test.ts (3 tests) 3008ms
✓ test A - 3s delay 3006ms
✓ test B - 3s delay 3007ms
✓ test C - 3s delay 3007ms
Test Files 1 passed (1)
Tests 3 passed (3)
Start at 14:59:03
Duration 3.08s (transform 9ms, setup 0ms, collect 13ms, tests 3.01s, environment 0ms, prepare 2ms)
~In your scenario where you run 100 tests concurrently, do you have 100 browsers running as well?~
Ah, I see that you are using @playwright/test for the API testing.
We are not too comfortable running tests in a single Node concurrently:
- a failure in one test can lead to the side-effects in the other tests
- unhandled errors can't be contributed to the failing test too
That, in combination with the regular @playwright/test application where the browser is present, produced the current architecture.
Sounds like you're trying to do API load testing, I would recommend k6 for this not Playwright
Sounds like you're trying to do API load testing, I would recommend k6 for this not Playwright
Hi, thanks for your reply. It is just lots of tests , with each having to wait a bit for verifying results.