chore: generate globalTimeout and maxFailures errors in runner (#30467)
Generate 'global timeout' and 'max failures' errors in the runner. Avoid reading `config.globalTimeout` and `config.maxFailures` in the base reporters. Reference https://github.com/microsoft/playwright/issues/29768
This commit is contained in:
parent
1e52c37b25
commit
1d786c804d
|
|
@ -194,8 +194,6 @@ export class BaseReporter implements ReporterV2 {
|
||||||
tokens.push(colors.yellow(` ${didNotRun} did not run`));
|
tokens.push(colors.yellow(` ${didNotRun} did not run`));
|
||||||
if (expected)
|
if (expected)
|
||||||
tokens.push(colors.green(` ${expected} passed`) + colors.dim(` (${milliseconds(this.result.duration)})`));
|
tokens.push(colors.green(` ${expected} passed`) + colors.dim(` (${milliseconds(this.result.duration)})`));
|
||||||
if (this.result.status === 'timedout')
|
|
||||||
tokens.push(colors.red(` Timed out waiting ${this.config.globalTimeout / 1000}s for the entire test run`));
|
|
||||||
if (fatalErrors.length && expected + unexpected.length + interrupted.length + flaky.length > 0)
|
if (fatalErrors.length && expected + unexpected.length + interrupted.length + flaky.length > 0)
|
||||||
tokens.push(colors.red(` ${fatalErrors.length === 1 ? '1 error was not a part of any test' : fatalErrors.length + ' errors were not a part of any test'}, see above for details`));
|
tokens.push(colors.red(` ${fatalErrors.length === 1 ? '1 error was not a part of any test' : fatalErrors.length + ' errors were not a part of any test'}, see above for details`));
|
||||||
|
|
||||||
|
|
@ -250,7 +248,6 @@ export class BaseReporter implements ReporterV2 {
|
||||||
if (full && summary.failuresToPrint.length && !this._omitFailures)
|
if (full && summary.failuresToPrint.length && !this._omitFailures)
|
||||||
this._printFailures(summary.failuresToPrint);
|
this._printFailures(summary.failuresToPrint);
|
||||||
this._printSlowTests();
|
this._printSlowTests();
|
||||||
this._printMaxFailuresReached();
|
|
||||||
this._printSummary(summaryMessage);
|
this._printSummary(summaryMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -272,14 +269,6 @@ export class BaseReporter implements ReporterV2 {
|
||||||
console.log(colors.yellow(' Consider splitting slow test files to speed up parallel execution'));
|
console.log(colors.yellow(' Consider splitting slow test files to speed up parallel execution'));
|
||||||
}
|
}
|
||||||
|
|
||||||
private _printMaxFailuresReached() {
|
|
||||||
if (!this.config.maxFailures)
|
|
||||||
return;
|
|
||||||
if (this._failureCount < this.config.maxFailures)
|
|
||||||
return;
|
|
||||||
console.log(colors.yellow(`Testing stopped early after ${this.config.maxFailures} maximum allowed failures.`));
|
|
||||||
}
|
|
||||||
|
|
||||||
private _printSummary(summary: string) {
|
private _printSummary(summary: string) {
|
||||||
if (summary.trim())
|
if (summary.trim())
|
||||||
console.log(summary);
|
console.log(summary);
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import type { TestGroup } from './testGroups';
|
||||||
import type { FullConfigInternal } from '../common/config';
|
import type { FullConfigInternal } from '../common/config';
|
||||||
import type { ReporterV2 } from '../reporters/reporterV2';
|
import type { ReporterV2 } from '../reporters/reporterV2';
|
||||||
import type { FailureTracker } from './failureTracker';
|
import type { FailureTracker } from './failureTracker';
|
||||||
|
import { colors } from 'playwright-core/lib/utilsBundle';
|
||||||
|
|
||||||
export type EnvByProjectId = Map<string, Record<string, string | undefined>>;
|
export type EnvByProjectId = Map<string, Record<string, string | undefined>>;
|
||||||
|
|
||||||
|
|
@ -540,9 +541,13 @@ class JobDispatcher {
|
||||||
|
|
||||||
private _reportTestEnd(test: TestCase, result: TestResult) {
|
private _reportTestEnd(test: TestCase, result: TestResult) {
|
||||||
this._reporter.onTestEnd(test, result);
|
this._reporter.onTestEnd(test, result);
|
||||||
|
const hadMaxFailures = this._failureTracker.hasReachedMaxFailures();
|
||||||
this._failureTracker.onTestEnd(test, result);
|
this._failureTracker.onTestEnd(test, result);
|
||||||
if (this._failureTracker.hasReachedMaxFailures())
|
if (this._failureTracker.hasReachedMaxFailures()) {
|
||||||
this._stopCallback();
|
this._stopCallback();
|
||||||
|
if (!hadMaxFailures)
|
||||||
|
this._reporter.onError({ message: colors.red(`Testing stopped early after ${this._failureTracker.maxFailures()} maximum allowed failures.`) });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,8 +40,7 @@ export class FailureTracker {
|
||||||
}
|
}
|
||||||
|
|
||||||
hasReachedMaxFailures() {
|
hasReachedMaxFailures() {
|
||||||
const maxFailures = this._config.config.maxFailures;
|
return this.maxFailures() > 0 && this._failureCount >= this.maxFailures();
|
||||||
return maxFailures > 0 && this._failureCount >= maxFailures;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hasWorkerErrors() {
|
hasWorkerErrors() {
|
||||||
|
|
@ -51,4 +50,8 @@ export class FailureTracker {
|
||||||
result(): 'failed' | 'passed' {
|
result(): 'failed' | 'passed' {
|
||||||
return this._hasWorkerErrors || this.hasReachedMaxFailures() || this._rootSuite?.allTests().some(test => !test.ok()) ? 'failed' : 'passed';
|
return this._hasWorkerErrors || this.hasReachedMaxFailures() || this._rootSuite?.allTests().some(test => !test.ok()) ? 'failed' : 'passed';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maxFailures() {
|
||||||
|
return this._config.config.maxFailures;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { debug } from 'playwright-core/lib/utilsBundle';
|
import { colors, debug } from 'playwright-core/lib/utilsBundle';
|
||||||
import { ManualPromise, monotonicTime } from 'playwright-core/lib/utils';
|
import { ManualPromise, monotonicTime } from 'playwright-core/lib/utils';
|
||||||
import type { FullResult, TestError } from '../../types/testReporter';
|
import type { FullResult, TestError } from '../../types/testReporter';
|
||||||
import { SigIntWatcher } from './sigIntWatcher';
|
import { SigIntWatcher } from './sigIntWatcher';
|
||||||
|
|
@ -99,7 +99,7 @@ export class TaskRunner<Context> {
|
||||||
if (sigintWatcher.hadSignal() || cancelPromise?.isDone()) {
|
if (sigintWatcher.hadSignal() || cancelPromise?.isDone()) {
|
||||||
status = 'interrupted';
|
status = 'interrupted';
|
||||||
} else if (timeoutWatcher.timedOut()) {
|
} else if (timeoutWatcher.timedOut()) {
|
||||||
this._reporter.onError?.({ message: `Timed out waiting ${this._globalTimeoutForError / 1000}s for the ${currentTaskName} to run` });
|
this._reporter.onError?.({ message: colors.red(`Timed out waiting ${this._globalTimeoutForError / 1000}s for the ${currentTaskName} to run`) });
|
||||||
status = 'timedout';
|
status = 'timedout';
|
||||||
} else if (this._hasErrors) {
|
} else if (this._hasErrors) {
|
||||||
status = 'failed';
|
status = 'failed';
|
||||||
|
|
|
||||||
|
|
@ -209,6 +209,32 @@ for (const useIntermediateMergeReport of [false, true] as const) {
|
||||||
expect(result.output).toContain('Testing stopped early after 1 maximum allowed failures.');
|
expect(result.output).toContain('Testing stopped early after 1 maximum allowed failures.');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should print if globalTimeout is reached', async ({ runInlineTest }) => {
|
||||||
|
test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/29768' });
|
||||||
|
const result = await runInlineTest({
|
||||||
|
'playwright.config.ts': `
|
||||||
|
module.exports = {
|
||||||
|
globalTimeout: 1000,
|
||||||
|
};
|
||||||
|
`,
|
||||||
|
'dir/a.test.js': `
|
||||||
|
import { test, expect } from '@playwright/test';
|
||||||
|
test('first', async ({}) => {
|
||||||
|
});
|
||||||
|
test('second (hanging)', async ({}) => {
|
||||||
|
await new Promise(() => {});
|
||||||
|
});
|
||||||
|
test('third', async ({}) => {
|
||||||
|
});
|
||||||
|
`,
|
||||||
|
});
|
||||||
|
expect(result.exitCode).toBe(1);
|
||||||
|
expect(result.passed).toBe(1);
|
||||||
|
expect(result.interrupted).toBe(1);
|
||||||
|
expect(result.didNotRun).toBe(1);
|
||||||
|
expect(result.output).toContain('Timed out waiting 1s for the test suite to run');
|
||||||
|
});
|
||||||
|
|
||||||
test('should not print slow parallel tests', async ({ runInlineTest }) => {
|
test('should not print slow parallel tests', async ({ runInlineTest }) => {
|
||||||
const result = await runInlineTest({
|
const result = await runInlineTest({
|
||||||
'playwright.config.ts': `
|
'playwright.config.ts': `
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue