From 50eb8bfcc1b64abcb790b123a452a023bdc68c8a Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Mon, 1 Apr 2024 11:02:31 +0900 Subject: [PATCH] feat: support running suites in parallel --- examples/basic/test/repro.test.ts | 40 ++++++++++++++++++++++++++++++ packages/runner/src/suite.ts | 5 +++- packages/runner/src/types/tasks.ts | 4 +++ 3 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 examples/basic/test/repro.test.ts diff --git a/examples/basic/test/repro.test.ts b/examples/basic/test/repro.test.ts new file mode 100644 index 000000000000..49d649974d54 --- /dev/null +++ b/examples/basic/test/repro.test.ts @@ -0,0 +1,40 @@ +import { describe, test } from 'vitest' + +const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)) + +// finishes in 3 sec +// (1st and 2nd suites in parallel) +describe('example-1', () => { + // finishes in 3 sec + // (1st and 2nd cases in serial) + describe('1st suite', { concurrentSuite: true }, () => { + test('1st case', async () => { + await sleep(1000) + }) + test('2nd case', async () => { + await sleep(2000) + }) + }) + + describe('2nd suite', { concurrentSuite: true }, () => { + test('1st case', async () => { + await sleep(1000) + }) + test('2nd case', async () => { + await sleep(2000) + }) + }) +}) + +// finishes in 3 sec +// (same as example-1 but implemented as describe.each) +describe('example-2', () => { + describe.each(['1st suite', '2nd suite'])('%s', { concurrentSuite: true }, () => { + test('1st case', async () => { + await sleep(1000) + }) + test('2nd case', async () => { + await sleep(2000) + }) + }) +}) diff --git a/packages/runner/src/suite.ts b/packages/runner/src/suite.ts index b1761b5c20fc..c039bb58a098 100644 --- a/packages/runner/src/suite.ts +++ b/packages/runner/src/suite.ts @@ -172,6 +172,7 @@ function createSuiteCollector(name: string, factory: SuiteFactory = () => { }, m if (typeof suiteOptions === 'object') options = Object.assign({}, suiteOptions, options) + // TODO: `this.concurrent/sequential` always undefined? // inherit concurrent / sequential from suite options.concurrent = this.concurrent || (!this.sequential && options?.concurrent) options.sequential = this.sequential || (!this.concurrent && options?.sequential) @@ -215,6 +216,7 @@ function createSuiteCollector(name: string, factory: SuiteFactory = () => { }, m tasks: [], meta: Object.create(null), projectName: '', + concurrent: suiteOptions?.concurrentSuite, } if (runner && includeLocation && runner.config.includeTaskLocation) { @@ -282,7 +284,8 @@ function createSuite() { if (currentSuite?.options) options = { ...currentSuite.options, ...options } - // inherit concurrent / sequential from current suite + // TODO: `this.concurrent/sequential` always undefined? + // inherit test concurrent / sequential from current suite options.concurrent = this.concurrent || (!this.sequential && options?.concurrent) options.sequential = this.sequential || (!this.concurrent && options?.sequential) diff --git a/packages/runner/src/types/tasks.ts b/packages/runner/src/types/tasks.ts index 9e1ac191dc92..063402f1bfff 100644 --- a/packages/runner/src/types/tasks.ts +++ b/packages/runner/src/types/tasks.ts @@ -185,6 +185,10 @@ export interface TestOptions { * Tests inherit `concurrent` from `describe()` and nested `describe()` will inherit from parent's `concurrent`. */ concurrent?: boolean + /** + * wip + */ + concurrentSuite?: boolean /** * Whether tests run sequentially. * Tests inherit `sequential` from `describe()` and nested `describe()` will inherit from parent's `sequential`.