fix(test runner): route more errors to reporter (#10263)

For example, top-level errors in files or global setup issues.
This commit is contained in:
Dmitry Gozman 2021-11-12 06:47:41 -08:00 committed by GitHub
parent d97fe4e2af
commit 4bb123d4b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 95 additions and 13 deletions

View File

@ -20,7 +20,7 @@ import * as fs from 'fs';
import * as path from 'path';
import { promisify } from 'util';
import { Dispatcher, TestGroup } from './dispatcher';
import { createFileMatcher, createTitleMatcher, FilePatternFilter, monotonicTime } from './util';
import { createFileMatcher, createTitleMatcher, FilePatternFilter, monotonicTime, serializeError } from './util';
import { TestCase, Suite } from './test';
import { Loader } from './loader';
import { FullResult, Reporter, TestError } from '../types/testReporter';
@ -97,18 +97,27 @@ export class Runner {
async run(list: boolean, filePatternFilters: FilePatternFilter[], projectNames?: string[]): Promise<FullResult> {
this._reporter = await this._createReporter(list);
const config = this._loader.fullConfig();
const globalDeadline = config.globalTimeout ? config.globalTimeout + monotonicTime() : 0;
const { result, timedOut } = await raceAgainstDeadline(this._run(list, filePatternFilters, projectNames), globalDeadline);
if (timedOut) {
const actualResult: FullResult = { status: 'timedout' };
if (this._didBegin)
await this._reporter.onEnd?.(actualResult);
else
this._reporter.onError?.(createStacklessError(`Timed out waiting ${config.globalTimeout / 1000}s for the entire test run`));
return actualResult;
try {
const config = this._loader.fullConfig();
const globalDeadline = config.globalTimeout ? config.globalTimeout + monotonicTime() : 0;
const { result, timedOut } = await raceAgainstDeadline(this._run(list, filePatternFilters, projectNames), globalDeadline);
if (timedOut) {
const actualResult: FullResult = { status: 'timedout' };
if (this._didBegin)
await this._reporter.onEnd?.(actualResult);
else
this._reporter.onError?.(createStacklessError(`Timed out waiting ${config.globalTimeout / 1000}s for the entire test run`));
return actualResult;
}
return result!;
} catch (e) {
const result: FullResult = { status: 'failed' };
try {
this._reporter.onError?.(serializeError(e));
} catch (ignored) {
}
return result;
}
return result!;
}
async _run(list: boolean, testFileReFilters: FilePatternFilter[], projectNames?: string[]): Promise<FullResult> {

View File

@ -26,7 +26,9 @@ class Reporter {
onStdErr() {}
onTestEnd(test, result) {}
onTimeout() {}
onError() {}
onError(error) {
console.log('\\n%%got error: ' + error.message);
}
onEnd() {
console.log('\\n%%end');
}
@ -405,6 +407,77 @@ test('should show nice stacks for locators', async ({ runInlineTest }) => {
]);
});
test('should report forbid-only error to reporter', async ({ runInlineTest }) => {
const result = await runInlineTest({
'reporter.ts': smallReporterJS,
'playwright.config.ts': `
module.exports = {
reporter: './reporter',
};
`,
'a.test.ts': `
pwt.test.only('pass', () => {});
`
}, { 'reporter': '', 'forbid-only': true });
expect(result.exitCode).toBe(1);
expect(result.output).toContain(`%%got error: =====================================\n --forbid-only found a focused test.`);
});
test('should report no-tests error to reporter', async ({ runInlineTest }) => {
const result = await runInlineTest({
'reporter.ts': smallReporterJS,
'playwright.config.ts': `
module.exports = {
reporter: './reporter',
};
`
}, { 'reporter': '' });
expect(result.exitCode).toBe(1);
expect(result.output).toContain(`%%got error: =================\n no tests found.`);
});
test('should report require error to reporter', async ({ runInlineTest }) => {
const result = await runInlineTest({
'reporter.ts': smallReporterJS,
'playwright.config.ts': `
module.exports = {
reporter: './reporter',
};
`,
'a.spec.js': `
throw new Error('Oh my!');
`,
}, { 'reporter': '' });
expect(result.exitCode).toBe(1);
expect(result.output).toContain(`%%got error: Oh my!`);
});
test('should report global setup error to reporter', async ({ runInlineTest }) => {
const result = await runInlineTest({
'reporter.ts': smallReporterJS,
'playwright.config.ts': `
module.exports = {
reporter: './reporter',
globalSetup: './globalSetup',
};
`,
'globalSetup.ts': `
module.exports = () => {
throw new Error('Oh my!');
};
`,
'a.spec.js': `
pwt.test('test', () => {});
`,
}, { 'reporter': '' });
expect(result.exitCode).toBe(1);
expect(result.output).toContain(`%%got error: Oh my!`);
});
function stripEscapedAscii(str: string) {
return str.replace(/\\u00[a-z0-9][a-z0-9]\[[^m]+m/g, '');
}