mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
fix(runner): fail if worker cannot find some of the tests (#13666)
This commit is contained in:
parent
3b159b45ff
commit
2e6ef8f622
@ -279,7 +279,7 @@ export class Dispatcher {
|
|||||||
// - there are no remaining
|
// - there are no remaining
|
||||||
// - we are here not because something failed
|
// - we are here not because something failed
|
||||||
// - no unrecoverable worker error
|
// - no unrecoverable worker error
|
||||||
if (!remaining.length && !failedTestIds.size && !params.fatalErrors.length && !params.skipTestsDueToSetupFailure.length) {
|
if (!remaining.length && !failedTestIds.size && !params.fatalErrors.length && !params.skipTestsDueToSetupFailure.length && !params.fatalUnknownTestIds) {
|
||||||
if (this._isWorkerRedundant(worker))
|
if (this._isWorkerRedundant(worker))
|
||||||
worker.stop();
|
worker.stop();
|
||||||
doneWithJob();
|
doneWithJob();
|
||||||
@ -322,6 +322,13 @@ export class Dispatcher {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (params.fatalUnknownTestIds) {
|
||||||
|
const titles = params.fatalUnknownTestIds.map(testId => {
|
||||||
|
const test = this._testById.get(testId)!.test;
|
||||||
|
return test.titlePath().slice(1).join(' > ');
|
||||||
|
});
|
||||||
|
massSkipTestsFromRemaining(new Set(params.fatalUnknownTestIds), [{ message: `Unknown test(s) in worker:\n${titles.join('\n')}` }]);
|
||||||
|
}
|
||||||
if (params.fatalErrors.length) {
|
if (params.fatalErrors.length) {
|
||||||
// In case of fatal errors, report first remaining test as failing with these errors,
|
// In case of fatal errors, report first remaining test as failing with these errors,
|
||||||
// and all others as skipped.
|
// and all others as skipped.
|
||||||
|
|||||||
@ -78,6 +78,7 @@ export type RunPayload = {
|
|||||||
export type DonePayload = {
|
export type DonePayload = {
|
||||||
fatalErrors: TestError[];
|
fatalErrors: TestError[];
|
||||||
skipTestsDueToSetupFailure: string[]; // test ids
|
skipTestsDueToSetupFailure: string[]; // test ids
|
||||||
|
fatalUnknownTestIds?: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TestOutputPayload = {
|
export type TestOutputPayload = {
|
||||||
|
|||||||
@ -157,6 +157,7 @@ export class WorkerRunner extends EventEmitter {
|
|||||||
async runTestGroup(runPayload: RunPayload) {
|
async runTestGroup(runPayload: RunPayload) {
|
||||||
this._runFinished = new ManualPromise<void>();
|
this._runFinished = new ManualPromise<void>();
|
||||||
const entries = new Map(runPayload.entries.map(e => [ e.testId, e ]));
|
const entries = new Map(runPayload.entries.map(e => [ e.testId, e ]));
|
||||||
|
let fatalUnknownTestIds;
|
||||||
try {
|
try {
|
||||||
await this._loadIfNeeded();
|
await this._loadIfNeeded();
|
||||||
const fileSuite = await this._loader.loadTestFile(runPayload.file, 'worker');
|
const fileSuite = await this._loader.loadTestFile(runPayload.file, 'worker');
|
||||||
@ -178,6 +179,9 @@ export class WorkerRunner extends EventEmitter {
|
|||||||
entries.delete(tests[i]._id);
|
entries.delete(tests[i]._id);
|
||||||
await this._runTest(tests[i], entry.retry, tests[i + 1]);
|
await this._runTest(tests[i], entry.retry, tests[i + 1]);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
fatalUnknownTestIds = runPayload.entries.map(e => e.testId);
|
||||||
|
this.stop();
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// In theory, we should run above code without any errors.
|
// In theory, we should run above code without any errors.
|
||||||
@ -188,6 +192,7 @@ export class WorkerRunner extends EventEmitter {
|
|||||||
const donePayload: DonePayload = {
|
const donePayload: DonePayload = {
|
||||||
fatalErrors: this._fatalErrors,
|
fatalErrors: this._fatalErrors,
|
||||||
skipTestsDueToSetupFailure: [],
|
skipTestsDueToSetupFailure: [],
|
||||||
|
fatalUnknownTestIds
|
||||||
};
|
};
|
||||||
for (const test of this._skipRemainingTestsInSuite?.allTests() || []) {
|
for (const test of this._skipRemainingTestsInSuite?.allTests() || []) {
|
||||||
if (entries.has(test._id))
|
if (entries.has(test._id))
|
||||||
|
|||||||
@ -248,3 +248,37 @@ test('should teardown workers that are redundant', async ({ runInlineTest }) =>
|
|||||||
'%%worker teardown',
|
'%%worker teardown',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should not hang if test suites in worker are inconsistent with runner', async ({ runInlineTest }) => {
|
||||||
|
const oldValue = process.env.TEST_WORKER_INDEX;
|
||||||
|
delete process.env.TEST_WORKER_INDEX;
|
||||||
|
const result = await runInlineTest({
|
||||||
|
'playwright.config.ts': `
|
||||||
|
module.exports = { name: 'project-name' };
|
||||||
|
`,
|
||||||
|
'names.js': `
|
||||||
|
exports.getNames = () => {
|
||||||
|
const inWorker = process.env.TEST_WORKER_INDEX !== undefined;
|
||||||
|
if (inWorker)
|
||||||
|
return ['foo'];
|
||||||
|
return ['foo', 'bar', 'baz'];
|
||||||
|
};
|
||||||
|
`,
|
||||||
|
'a.spec.js': `
|
||||||
|
const { test } = pwt;
|
||||||
|
const { getNames } = require('./names');
|
||||||
|
const names = getNames();
|
||||||
|
for (const index in names) {
|
||||||
|
test('Test ' + index + ' - ' + names[index], async () => {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
}, { 'workers': 1 });
|
||||||
|
process.env.TEST_WORKER_INDEX = oldValue;
|
||||||
|
expect(result.exitCode).toBe(1);
|
||||||
|
expect(result.passed).toBe(1);
|
||||||
|
expect(result.failed).toBe(1);
|
||||||
|
expect(result.skipped).toBe(1);
|
||||||
|
expect(result.report.suites[0].specs[1].tests[0].results[0].error.message).toBe('Unknown test(s) in worker:\nproject-name > a.spec.js > Test 1 - bar\nproject-name > a.spec.js > Test 2 - baz');
|
||||||
|
});
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user