Skip to content

Commit addf6f7

Browse files
feat(reporter): expose suite execution modes during preprocess (#43758)
Co-authored-by: microsoft-playwright-automation[bot] <203992400+microsoft-playwright-automation[bot]@users.noreply.github.com>
1 parent 6764853 commit addf6f7

4 files changed

Lines changed: 101 additions & 12 deletions

File tree

‎docs/src/test-reporter-api/class-testrun.md‎

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* since: v1.62
33
* langs: js
44

5-
Controls which tests will run and their expected status. A [TestRun] is available during [`method: Reporter.preprocess`]. Setup and teardown projects cannot be changed.
5+
Controls which tests will run and their expected status, and provides information about suite execution modes. A [TestRun] is available during [`method: Reporter.preprocess`]. Setup and teardown projects cannot be changed.
66

77
## method: TestRun.exclude
88
* since: v1.62
@@ -49,6 +49,23 @@ Test or suite to mark as fixme.
4949

5050
Optional explanation surfaced as the annotation description.
5151

52+
## method: TestRun.mode
53+
* since: v1.65
54+
- returns: "TestMode" <"serial"|"parallel"|"default">
55+
56+
Returns the execution mode configured for a suite with [`method: Test.describe.configure`], [`method: Test.describe.serial`] or [`method: Test.describe.parallel`].
57+
If the suite does not configure a mode, it inherits its parent's mode. Project suites use `"parallel"` when [`property: TestProject.fullyParallel`] is enabled, and `"default"` otherwise. The root suite uses `"default"`.
58+
59+
An explicit `"default"` suite does not inherit `"parallel"` from its parent: its tests run in order in the same worker. The mode alone does not describe complete test groups, which also depend on worker fixtures and hooks.
60+
61+
This method can only be called during [`method: Reporter.preprocess`], and can also inspect setup and teardown projects.
62+
63+
### param: TestRun.mode.suite
64+
* since: v1.65
65+
- `suite` <[Suite]>
66+
67+
Suite to inspect.
68+
5269
## method: TestRun.skip
5370
* since: v1.62
5471

‎packages/playwright/src/runner/reporterTestRun.ts‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,16 @@ export class ReporterTestRunImpl implements ReporterTestRun {
3434
return this._skipSharding;
3535
}
3636

37+
mode(suite: ReporterSuite): 'serial' | 'parallel' | 'default' {
38+
if (!this._active)
39+
throw new Error(`TestRun.mode() can only be called from Reporter.preprocess().`);
40+
for (let current: testNs.Suite | undefined = suite as testNs.Suite; current; current = current.parent) {
41+
if (current._parallelMode !== 'none')
42+
return current._parallelMode;
43+
}
44+
return 'default';
45+
}
46+
3747
skipSharding() {
3848
if (!this._active)
3949
throw new Error(`TestRun.skipSharding() can only be called from Reporter.preprocess().`);

‎packages/playwright/types/testReporter.d.ts‎

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -752,8 +752,8 @@ export interface TestResult {
752752
}
753753

754754
/**
755-
* Controls which tests will run and their expected status. A [TestRun](https://playwright.dev/docs/api/class-testrun)
756-
* is available during
755+
* Controls which tests will run and their expected status, and provides information about suite execution modes. A
756+
* [TestRun](https://playwright.dev/docs/api/class-testrun) is available during
757757
* [reporter.preprocess(params)](https://playwright.dev/docs/api/class-reporter#reporter-preprocess). Setup and
758758
* teardown projects cannot be changed.
759759
*/
@@ -781,6 +781,26 @@ export interface TestRun {
781781
*/
782782
fixme(test: TestCase|Suite, reason?: string): void;
783783

784+
/**
785+
* Returns the execution mode configured for a suite with
786+
* [test.describe.configure([options])](https://playwright.dev/docs/api/class-test#test-describe-configure),
787+
* [test.describe.serial([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe-serial)
788+
* or
789+
* [test.describe.parallel([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe-parallel).
790+
* If the suite does not configure a mode, it inherits its parent's mode. Project suites use `"parallel"` when
791+
* [testProject.fullyParallel](https://playwright.dev/docs/api/class-testproject#test-project-fully-parallel) is
792+
* enabled, and `"default"` otherwise. The root suite uses `"default"`.
793+
*
794+
* An explicit `"default"` suite does not inherit `"parallel"` from its parent: its tests run in order in the same
795+
* worker. The mode alone does not describe complete test groups, which also depend on worker fixtures and hooks.
796+
*
797+
* This method can only be called during
798+
* [reporter.preprocess(params)](https://playwright.dev/docs/api/class-reporter#reporter-preprocess), and can also
799+
* inspect setup and teardown projects.
800+
* @param suite Suite to inspect.
801+
*/
802+
mode(suite: Suite): "serial"|"parallel"|"default";
803+
784804
/**
785805
* Skips a test or every test in a suite. The test bodies are not executed and the tests are reported as skipped.
786806
* @param test Test or suite to skip.

‎tests/playwright-test/reporter-preprocess.spec.ts‎

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ test('TestRun methods throw outside preprocess, and the root suite cannot be exc
194194
const testCase = suite.allTests()[0];
195195
const fileSuite = testCase.parent;
196196
for (const [label, obj] of [['TestCase', testCase], ['Suite', fileSuite]]) {
197-
for (const method of ['skip', 'fixme', 'fail', 'exclude']) {
197+
for (const method of ['skip', 'fixme', 'fail', 'exclude', ...(label === 'Suite' ? ['mode'] : [])]) {
198198
try {
199199
this.testRun[method](obj);
200200
console.log('%% ' + label + '.' + method + ': no-throw');
@@ -225,6 +225,7 @@ test('TestRun methods throw outside preprocess, and the root suite cannot be exc
225225
'Suite.fixme: TestRun.fixme() can only be called from Reporter.preprocess().',
226226
'Suite.fail: TestRun.fail() can only be called from Reporter.preprocess().',
227227
'Suite.exclude: TestRun.exclude() can only be called from Reporter.preprocess().',
228+
'Suite.mode: TestRun.mode() can only be called from Reporter.preprocess().',
228229
]);
229230
});
230231

@@ -436,6 +437,8 @@ test('plan.suite exposes setup/teardown dependency projects but they are read-on
436437
}
437438
}
438439
const setupProject = suite.suites.find(s => s.title === 'setup');
440+
console.log('%% setup mode: ' + testRun.mode(setupProject));
441+
console.log('%% teardown mode: ' + testRun.mode(suite.suites.find(s => s.title === 'teardown')));
439442
try {
440443
testRun.exclude(setupProject);
441444
console.log('%% dep-suite-exclude: no-throw');
@@ -491,6 +494,8 @@ test('plan.suite exposes setup/teardown dependency projects but they are read-on
491494
'dep-fixme: TestRun.fixme() cannot be called on a setup or teardown project test; these always run in full.',
492495
'dep-fail: TestRun.fail() cannot be called on a setup or teardown project test; these always run in full.',
493496
'dep-exclude: TestRun.exclude() cannot be called on a setup or teardown project test; these always run in full.',
497+
'setup mode: default',
498+
'teardown mode: default',
494499
'dep-suite-exclude: TestRun.exclude() cannot be called on a setup or teardown project; these always run in full.',
495500
'same test objects: true',
496501
'dep-after-preprocess: TestRun.skip() can only be called from Reporter.preprocess().',
@@ -547,18 +552,29 @@ test('plan.suite temporarily exposes dependencies without changing final project
547552
]);
548553
});
549554

550-
test('serial suites expose a serial annotation for custom sharding', async ({ runInlineTest }) => {
555+
test('suite modes and serial annotations are available for custom sharding', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/43602' } }, async ({ runInlineTest }) => {
551556
const result = await runInlineTest({
552557
'reporter.ts': `
553558
class Reporter {
554-
async preprocess({ suite }) {
559+
async preprocess({ suite, testRun }) {
560+
console.log('%% root:' + testRun.mode(suite));
561+
for (const project of suite.suites) {
562+
console.log('%% project ' + project.title + ':' + testRun.mode(project));
563+
console.log('%% file ' + project.title + ':' + testRun.mode(project.suites[0]));
564+
}
555565
for (const t of suite.allTests())
556-
console.log('%% ' + t.title + ':' + t.annotations.filter(a => a.type === 'serial').length);
566+
console.log('%% ' + t.parent.project().name + '/' + t.title + ':' + t.annotations.filter(a => a.type === 'serial').length + ':' + testRun.mode(t.parent));
557567
}
558568
}
559569
export default Reporter;
560570
`,
561-
'playwright.config.ts': `export default { reporter: './reporter.ts' };`,
571+
'playwright.config.ts': `
572+
export default {
573+
reporter: './reporter.ts',
574+
fullyParallel: true,
575+
projects: [{ name: 'parallel' }, { name: 'default', fullyParallel: false }],
576+
};
577+
`,
562578
'a.test.ts': `
563579
import { test } from '@playwright/test';
564580
test('plain', async () => {});
@@ -570,17 +586,43 @@ test('serial suites expose a serial annotation for custom sharding', async ({ ru
570586
test('configure', async () => {});
571587
});
572588
test.describe.serial('outer', () => {
589+
test.describe('inherited serial', () => {
590+
test('inherited-serial', async () => {});
591+
});
573592
test.describe.serial('inner', () => {
574593
test('nested', async () => {});
575594
});
576595
});
596+
test.describe.parallel('parallel', () => {
597+
test.describe('inherited parallel', () => {
598+
test('inherited-parallel', async () => {});
599+
});
600+
test.describe('default', () => {
601+
test.describe.configure({ mode: 'default' });
602+
test('default-one', async () => {});
603+
test.describe('inherited default', () => {
604+
test('default-two', async () => {});
605+
});
606+
});
607+
});
577608
`,
578609
}, { reporter: '', workers: 1 });
579610
expect(result.exitCode).toBe(0);
580611
expect(result.outputLines).toEqual([
581-
'plain:0',
582-
'serial:1',
583-
'configure:1',
584-
'nested:2',
612+
'root:default',
613+
'project parallel:parallel',
614+
'file parallel:parallel',
615+
'project default:default',
616+
'file default:default',
617+
...['parallel', 'default'].flatMap(project => [
618+
project + '/plain:0:' + project,
619+
project + '/serial:1:serial',
620+
project + '/configure:1:serial',
621+
project + '/inherited-serial:1:serial',
622+
project + '/nested:2:serial',
623+
project + '/inherited-parallel:0:parallel',
624+
project + '/default-one:0:default',
625+
project + '/default-two:0:default',
626+
]),
585627
]);
586628
});

0 commit comments

Comments
 (0)