From 2b499bd5d6f956a7d08638ed3f717d26660325a6 Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Sat, 28 Jan 2023 09:30:42 -0800 Subject: [PATCH] chore: create tests groups per project (#20463) --- packages/playwright-test/src/runner/runner.ts | 1 + packages/playwright-test/src/runner/tasks.ts | 34 ++++---- .../playwright-test/src/runner/testGroups.ts | 78 +++++++++---------- 3 files changed, 56 insertions(+), 57 deletions(-) diff --git a/packages/playwright-test/src/runner/runner.ts b/packages/playwright-test/src/runner/runner.ts index 48566e0eb6..68e2fa7842 100644 --- a/packages/playwright-test/src/runner/runner.ts +++ b/packages/playwright-test/src/runner/runner.ts @@ -74,6 +74,7 @@ export class Runner { options, reporter, plugins: [], + testGroups: [], }; reporter.onConfigure(config); diff --git a/packages/playwright-test/src/runner/tasks.ts b/packages/playwright-test/src/runner/tasks.ts index 613ae328aa..f87f385985 100644 --- a/packages/playwright-test/src/runner/tasks.ts +++ b/packages/playwright-test/src/runner/tasks.ts @@ -46,8 +46,8 @@ export type TaskRunnerState = { reporter: Multiplexer; config: FullConfigInternal; plugins: TestRunnerPlugin[]; + testGroups: TestGroup[]; rootSuite?: Suite; - testGroups?: TestGroup[]; dispatcher?: Dispatcher; }; @@ -59,7 +59,7 @@ export function createTaskRunner(config: FullConfigInternal, reporter: Multiplex if (config.globalSetup || config.globalTeardown) taskRunner.addTask('global setup', createGlobalSetupTask()); taskRunner.addTask('load tests', createLoadTask()); - + taskRunner.addTask('shard tests', createTestGroupsTask()); taskRunner.addTask('prepare to run', createRemoveOutputDirsTask()); taskRunner.addTask('plugin begin', async ({ rootSuite, plugins }) => { for (const plugin of plugins) @@ -158,22 +158,22 @@ export function createRemoveOutputDirsTask(): Task { function createLoadTask(): Task { return async (context, errors) => { const { config, reporter, options } = context; - const rootSuite = await loadAllTests(config, reporter, options, errors); - const testGroups = options.listOnly ? [] : createTestGroups(rootSuite.suites, config.workers); - - context.rootSuite = rootSuite; - context.testGroups = testGroups; - if (errors.length) - return; - + context.rootSuite = await loadAllTests(config, reporter, options, errors); // Fail when no tests. - if (!rootSuite.allTests().length && !context.options.passWithNoTests) + if (!context.rootSuite.allTests().length && !context.options.passWithNoTests) throw new Error(`No tests found`); - - if (!context.options.listOnly) { - if (context.config.shard) - filterForShard(context.config.shard, rootSuite, testGroups); - context.config._maxConcurrentTestGroups = testGroups.length; - } + }; +} + +function createTestGroupsTask(): Task { + return async context => { + const { config, rootSuite } = context; + + for (const projectSuite of rootSuite!.suites) + context.testGroups.push(...createTestGroups(projectSuite, config.workers)); + + if (context.config.shard) + filterForShard(context.config.shard, rootSuite!, context.testGroups); + context.config._maxConcurrentTestGroups = context.testGroups.length; }; } diff --git a/packages/playwright-test/src/runner/testGroups.ts b/packages/playwright-test/src/runner/testGroups.ts index efa2e0d781..0497fd4b74 100644 --- a/packages/playwright-test/src/runner/testGroups.ts +++ b/packages/playwright-test/src/runner/testGroups.ts @@ -25,7 +25,7 @@ export type TestGroup = { tests: TestCase[]; }; -export function createTestGroups(projectSuites: Suite[], workers: number): TestGroup[] { +export function createTestGroups(projectSuite: Suite, workers: number): TestGroup[] { // This function groups tests that can be run together. // Tests cannot be run together when: // - They belong to different projects - requires different workers. @@ -62,49 +62,47 @@ export function createTestGroups(projectSuites: Suite[], workers: number): TestG }; }; - for (const projectSuite of projectSuites) { - for (const test of projectSuite.allTests()) { - let withWorkerHash = groups.get(test._workerHash); - if (!withWorkerHash) { - withWorkerHash = new Map(); - groups.set(test._workerHash, withWorkerHash); - } - let withRequireFile = withWorkerHash.get(test._requireFile); - if (!withRequireFile) { - withRequireFile = { - general: createGroup(test), - parallel: new Map(), - parallelWithHooks: createGroup(test), - }; - withWorkerHash.set(test._requireFile, withRequireFile); - } + for (const test of projectSuite.allTests()) { + let withWorkerHash = groups.get(test._workerHash); + if (!withWorkerHash) { + withWorkerHash = new Map(); + groups.set(test._workerHash, withWorkerHash); + } + let withRequireFile = withWorkerHash.get(test._requireFile); + if (!withRequireFile) { + withRequireFile = { + general: createGroup(test), + parallel: new Map(), + parallelWithHooks: createGroup(test), + }; + withWorkerHash.set(test._requireFile, withRequireFile); + } - // Note that a parallel suite cannot be inside a serial suite. This is enforced in TestType. - let insideParallel = false; - let outerMostSerialSuite: Suite | undefined; - let hasAllHooks = false; - for (let parent: Suite | undefined = test.parent; parent; parent = parent.parent) { - if (parent._parallelMode === 'serial') - outerMostSerialSuite = parent; - insideParallel = insideParallel || parent._parallelMode === 'parallel'; - hasAllHooks = hasAllHooks || parent._hooks.some(hook => hook.type === 'beforeAll' || hook.type === 'afterAll'); - } + // Note that a parallel suite cannot be inside a serial suite. This is enforced in TestType. + let insideParallel = false; + let outerMostSerialSuite: Suite | undefined; + let hasAllHooks = false; + for (let parent: Suite | undefined = test.parent; parent; parent = parent.parent) { + if (parent._parallelMode === 'serial') + outerMostSerialSuite = parent; + insideParallel = insideParallel || parent._parallelMode === 'parallel'; + hasAllHooks = hasAllHooks || parent._hooks.some(hook => hook.type === 'beforeAll' || hook.type === 'afterAll'); + } - if (insideParallel) { - if (hasAllHooks && !outerMostSerialSuite) { - withRequireFile.parallelWithHooks.tests.push(test); - } else { - const key = outerMostSerialSuite || test; - let group = withRequireFile.parallel.get(key); - if (!group) { - group = createGroup(test); - withRequireFile.parallel.set(key, group); - } - group.tests.push(test); - } + if (insideParallel) { + if (hasAllHooks && !outerMostSerialSuite) { + withRequireFile.parallelWithHooks.tests.push(test); } else { - withRequireFile.general.tests.push(test); + const key = outerMostSerialSuite || test; + let group = withRequireFile.parallel.get(key); + if (!group) { + group = createGroup(test); + withRequireFile.parallel.set(key, group); + } + group.tests.push(test); } + } else { + withRequireFile.general.tests.push(test); } }