@@ -313,7 +313,7 @@ export class Runner {
313313 fatalErrors . push ( createNoTestsError ( ) ) ;
314314
315315 // 8. Compute shards.
316- let testGroups = createTestGroups ( rootSuite ) ;
316+ let testGroups = createTestGroups ( rootSuite , config . workers ) ;
317317
318318 const shard = config . shard ;
319319 if ( shard ) {
@@ -619,7 +619,7 @@ function buildItemLocation(rootDir: string, testOrSuite: Suite | TestCase) {
619619 return `${ path . relative ( rootDir , testOrSuite . location . file ) } :${ testOrSuite . location . line } ` ;
620620}
621621
622- function createTestGroups ( rootSuite : Suite ) : TestGroup [ ] {
622+ function createTestGroups ( rootSuite : Suite , workers : number ) : TestGroup [ ] {
623623 // This function groups tests that can be run together.
624624 // Tests cannot be run together when:
625625 // - They belong to different projects - requires different workers.
@@ -630,7 +630,15 @@ function createTestGroups(rootSuite: Suite): TestGroup[] {
630630
631631 // Using the map "workerHash -> requireFile -> group" makes us preserve the natural order
632632 // of worker hashes and require files for the simple cases.
633- const groups = new Map < string , Map < string , { general : TestGroup , parallel : TestGroup [ ] } > > ( ) ;
633+ const groups = new Map < string , Map < string , {
634+ // Tests that must be run in order are in the same group.
635+ general : TestGroup ,
636+ // Tests that may be run independently each has a dedicated group with a single test.
637+ parallel : TestGroup [ ] ,
638+ // Tests that are marked as parallel but have beforeAll/afterAll hooks should be grouped
639+ // as much as possible. We split them into equally sized groups, one per worker.
640+ parallelWithHooks : TestGroup ,
641+ } > > ( ) ;
634642
635643 const createGroup = ( test : TestCase ) : TestGroup => {
636644 return {
@@ -654,18 +662,26 @@ function createTestGroups(rootSuite: Suite): TestGroup[] {
654662 withRequireFile = {
655663 general : createGroup ( test ) ,
656664 parallel : [ ] ,
665+ parallelWithHooks : createGroup ( test ) ,
657666 } ;
658667 withWorkerHash . set ( test . _requireFile , withRequireFile ) ;
659668 }
660669
661670 let insideParallel = false ;
662- for ( let parent : Suite | undefined = test . parent ; parent ; parent = parent . parent )
671+ let hasAllHooks = false ;
672+ for ( let parent : Suite | undefined = test . parent ; parent ; parent = parent . parent ) {
663673 insideParallel = insideParallel || parent . _parallelMode === 'parallel' ;
674+ hasAllHooks = hasAllHooks || parent . hooks . length > 0 ;
675+ }
664676
665677 if ( insideParallel ) {
666- const group = createGroup ( test ) ;
667- group . tests . push ( test ) ;
668- withRequireFile . parallel . push ( group ) ;
678+ if ( hasAllHooks ) {
679+ withRequireFile . parallelWithHooks . tests . push ( test ) ;
680+ } else {
681+ const group = createGroup ( test ) ;
682+ group . tests . push ( test ) ;
683+ withRequireFile . parallel . push ( group ) ;
684+ }
669685 } else {
670686 withRequireFile . general . tests . push ( test ) ;
671687 }
@@ -678,6 +694,16 @@ function createTestGroups(rootSuite: Suite): TestGroup[] {
678694 if ( withRequireFile . general . tests . length )
679695 result . push ( withRequireFile . general ) ;
680696 result . push ( ...withRequireFile . parallel ) ;
697+
698+ const parallelWithHooksGroupSize = Math . ceil ( withRequireFile . parallelWithHooks . tests . length / workers ) ;
699+ let lastGroup : TestGroup | undefined ;
700+ for ( const test of withRequireFile . parallelWithHooks . tests ) {
701+ if ( ! lastGroup || lastGroup . tests . length >= parallelWithHooksGroupSize ) {
702+ lastGroup = createGroup ( test ) ;
703+ result . push ( lastGroup ) ;
704+ }
705+ lastGroup . tests . push ( test ) ;
706+ }
681707 }
682708 }
683709 return result ;
0 commit comments