chore: create tests groups per project (#20463)
This commit is contained in:
parent
7cb1b2db39
commit
2b499bd5d6
|
|
@ -74,6 +74,7 @@ export class Runner {
|
||||||
options,
|
options,
|
||||||
reporter,
|
reporter,
|
||||||
plugins: [],
|
plugins: [],
|
||||||
|
testGroups: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
reporter.onConfigure(config);
|
reporter.onConfigure(config);
|
||||||
|
|
|
||||||
|
|
@ -46,8 +46,8 @@ export type TaskRunnerState = {
|
||||||
reporter: Multiplexer;
|
reporter: Multiplexer;
|
||||||
config: FullConfigInternal;
|
config: FullConfigInternal;
|
||||||
plugins: TestRunnerPlugin[];
|
plugins: TestRunnerPlugin[];
|
||||||
|
testGroups: TestGroup[];
|
||||||
rootSuite?: Suite;
|
rootSuite?: Suite;
|
||||||
testGroups?: TestGroup[];
|
|
||||||
dispatcher?: Dispatcher;
|
dispatcher?: Dispatcher;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -59,7 +59,7 @@ export function createTaskRunner(config: FullConfigInternal, reporter: Multiplex
|
||||||
if (config.globalSetup || config.globalTeardown)
|
if (config.globalSetup || config.globalTeardown)
|
||||||
taskRunner.addTask('global setup', createGlobalSetupTask());
|
taskRunner.addTask('global setup', createGlobalSetupTask());
|
||||||
taskRunner.addTask('load tests', createLoadTask());
|
taskRunner.addTask('load tests', createLoadTask());
|
||||||
|
taskRunner.addTask('shard tests', createTestGroupsTask());
|
||||||
taskRunner.addTask('prepare to run', createRemoveOutputDirsTask());
|
taskRunner.addTask('prepare to run', createRemoveOutputDirsTask());
|
||||||
taskRunner.addTask('plugin begin', async ({ rootSuite, plugins }) => {
|
taskRunner.addTask('plugin begin', async ({ rootSuite, plugins }) => {
|
||||||
for (const plugin of plugins)
|
for (const plugin of plugins)
|
||||||
|
|
@ -158,22 +158,22 @@ export function createRemoveOutputDirsTask(): Task<TaskRunnerState> {
|
||||||
function createLoadTask(): Task<TaskRunnerState> {
|
function createLoadTask(): Task<TaskRunnerState> {
|
||||||
return async (context, errors) => {
|
return async (context, errors) => {
|
||||||
const { config, reporter, options } = context;
|
const { config, reporter, options } = context;
|
||||||
const rootSuite = await loadAllTests(config, reporter, options, errors);
|
context.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;
|
|
||||||
|
|
||||||
// Fail when no tests.
|
// 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`);
|
throw new Error(`No tests found`);
|
||||||
|
};
|
||||||
if (!context.options.listOnly) {
|
}
|
||||||
if (context.config.shard)
|
|
||||||
filterForShard(context.config.shard, rootSuite, testGroups);
|
function createTestGroupsTask(): Task<TaskRunnerState> {
|
||||||
context.config._maxConcurrentTestGroups = testGroups.length;
|
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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ export type TestGroup = {
|
||||||
tests: TestCase[];
|
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.
|
// This function groups tests that can be run together.
|
||||||
// Tests cannot be run together when:
|
// Tests cannot be run together when:
|
||||||
// - They belong to different projects - requires different workers.
|
// - 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()) {
|
||||||
for (const test of projectSuite.allTests()) {
|
let withWorkerHash = groups.get(test._workerHash);
|
||||||
let withWorkerHash = groups.get(test._workerHash);
|
if (!withWorkerHash) {
|
||||||
if (!withWorkerHash) {
|
withWorkerHash = new Map();
|
||||||
withWorkerHash = new Map();
|
groups.set(test._workerHash, withWorkerHash);
|
||||||
groups.set(test._workerHash, withWorkerHash);
|
}
|
||||||
}
|
let withRequireFile = withWorkerHash.get(test._requireFile);
|
||||||
let withRequireFile = withWorkerHash.get(test._requireFile);
|
if (!withRequireFile) {
|
||||||
if (!withRequireFile) {
|
withRequireFile = {
|
||||||
withRequireFile = {
|
general: createGroup(test),
|
||||||
general: createGroup(test),
|
parallel: new Map(),
|
||||||
parallel: new Map(),
|
parallelWithHooks: createGroup(test),
|
||||||
parallelWithHooks: createGroup(test),
|
};
|
||||||
};
|
withWorkerHash.set(test._requireFile, withRequireFile);
|
||||||
withWorkerHash.set(test._requireFile, withRequireFile);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Note that a parallel suite cannot be inside a serial suite. This is enforced in TestType.
|
// Note that a parallel suite cannot be inside a serial suite. This is enforced in TestType.
|
||||||
let insideParallel = false;
|
let insideParallel = false;
|
||||||
let outerMostSerialSuite: Suite | undefined;
|
let outerMostSerialSuite: Suite | undefined;
|
||||||
let hasAllHooks = false;
|
let hasAllHooks = false;
|
||||||
for (let parent: Suite | undefined = test.parent; parent; parent = parent.parent) {
|
for (let parent: Suite | undefined = test.parent; parent; parent = parent.parent) {
|
||||||
if (parent._parallelMode === 'serial')
|
if (parent._parallelMode === 'serial')
|
||||||
outerMostSerialSuite = parent;
|
outerMostSerialSuite = parent;
|
||||||
insideParallel = insideParallel || parent._parallelMode === 'parallel';
|
insideParallel = insideParallel || parent._parallelMode === 'parallel';
|
||||||
hasAllHooks = hasAllHooks || parent._hooks.some(hook => hook.type === 'beforeAll' || hook.type === 'afterAll');
|
hasAllHooks = hasAllHooks || parent._hooks.some(hook => hook.type === 'beforeAll' || hook.type === 'afterAll');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (insideParallel) {
|
if (insideParallel) {
|
||||||
if (hasAllHooks && !outerMostSerialSuite) {
|
if (hasAllHooks && !outerMostSerialSuite) {
|
||||||
withRequireFile.parallelWithHooks.tests.push(test);
|
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);
|
|
||||||
}
|
|
||||||
} else {
|
} 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue