@@ -234,6 +234,7 @@ class Workers extends EventEmitter {
234234 this . setMaxListeners ( 50 )
235235 this . codecept = initializeCodecept ( config . testConfig , config . options )
236236 this . options = config . options || { }
237+ this . config = config
237238 this . errors = [ ]
238239 this . numberOfWorkers = 0
239240 this . closedWorkers = 0
@@ -683,73 +684,119 @@ class Workers extends EventEmitter {
683684 * @private
684685 */
685686 _printEnhancedWorkersSummary ( result , testsByFeature , testsByWorker ) {
686- // Calculate accurate stats from actual test objects instead of relying on Container stats
687- // which may not aggregate correctly in all scenarios
688- let actualPassed = 0
689- let actualFailed = 0
690- let actualPending = 0
691-
692- result . tests . forEach ( test => {
693- if ( test . state === 'passed' ) actualPassed ++
694- else if ( test . state === 'failed' ) actualFailed ++
695- else if ( test . state === 'pending' || test . state === 'skipped' ) actualPending ++
696- } )
697-
698- const actualTotal = result . tests . length
699- const actualFailedHooks = result . stats ?. failedHooks || 0
687+ const stats = result . stats
700688
701689 // Use result.duration (wall-clock time) instead of stats.duration (which gets overwritten)
702- const duration = result . duration || result . stats ?. duration || 0
690+ const duration = result . duration || stats . duration || 0
691+ const separator = '═' . repeat ( 82 )
692+ const subSeparator = '─' . repeat ( 82 )
693+
694+ // Determine strategy
695+ let strategy = 'test'
696+ if ( this . isPoolMode ) {
697+ strategy = 'pool'
698+ } else if ( this . config && this . config . by === 'suite' ) {
699+ strategy = 'suite'
700+ }
701+
703702 output . print ( )
704- output . print ( output . styles . bold ( '-- TEST SUMMARY:' ) )
703+ output . print ( separator )
704+ output . print ( output . styles . bold ( ' 📊 ENHANCED SUMMARY' ) )
705+ output . print ( separator )
706+ output . print ( )
707+
708+ // Print overall metrics first - use stats for backward compatibility with existing tests
709+ output . print ( output . styles . bold ( 'OVERALL METRICS' ) )
710+ output . print ( subSeparator )
711+ const totalTests = stats . tests || 0
712+ const passRate = totalTests > 0 ? Math . round ( ( stats . passes / totalTests ) * 100 ) : 0
713+ const failRate = totalTests > 0 ? Math . round ( ( stats . failures / totalTests ) * 100 ) : 0
714+ const pendingRate = totalTests > 0 ? Math . round ( ( stats . pending / totalTests ) * 100 ) : 0
715+
716+ output . print ( `Total Tests: ${ totalTests } ` )
717+ output . print ( `${ output . styles . success ( '✓' ) } Passed: ${ output . styles . success ( stats . passes ) } (${ passRate } %)` )
718+ if ( stats . failures > 0 ) {
719+ output . print ( `${ output . styles . error ( '✗' ) } Failed: ${ output . styles . error ( stats . failures ) } (${ failRate } %)` )
720+ }
721+ if ( stats . pending > 0 ) {
722+ output . print ( `⊘ Pending: ${ stats . pending } (${ pendingRate } %)` )
723+ }
724+ if ( stats . failedHooks > 0 ) {
725+ output . print ( `${ output . styles . error ( '✗' ) } Failed Hooks: ${ output . styles . error ( stats . failedHooks ) } ` )
726+ }
727+ output . print ( `Duration: ${ ms ( duration ) } ` )
728+ output . print ( `Strategy: ${ strategy } ` )
729+ output . print ( separator )
705730 output . print ( )
706731
707732 // Print tests grouped by feature
708733 if ( Object . keys ( testsByFeature ) . length > 0 ) {
709- output . print ( output . styles . bold ( 'Results by Feature:' ) )
734+ output . print ( output . styles . bold ( 'BY FEATURE' ) )
735+ output . print ( subSeparator )
710736 Object . entries ( testsByFeature ) . forEach ( ( [ featureName , data ] ) => {
711- const totalTests = data . tests . length
712- const passRate = totalTests > 0 ? Math . round ( ( data . passed / totalTests ) * 100 ) : 0
713- const status = data . failed > 0 ? output . styles . error ( '✗' ) : output . styles . success ( '✓' )
714- output . print ( ` ${ status } ${ output . styles . bold ( featureName ) } ` )
715- output . print ( ` Passed: ${ output . styles . success ( data . passed ) } | Failed: ${ output . styles . error ( data . failed ) } | Skipped: ${ data . skipped } | Pass Rate: ${ passRate } %` )
737+ const totalFeatureTests = data . tests . length
738+ const featurePassRate = totalFeatureTests > 0 ? Math . round ( ( data . passed / totalFeatureTests ) * 100 ) : 0
739+ const featureDuration = data . tests . reduce ( ( acc , test ) => acc + ( test . duration || 0 ) , 0 )
740+
741+ output . print ( `📁 ${ output . styles . bold ( featureName ) } ` )
742+
743+ const parts = [ ` Total: ${ totalFeatureTests } ` ]
744+ if ( data . passed > 0 ) {
745+ parts . push ( `${ output . styles . success ( '✓' ) } Passed: ${ data . passed } (${ featurePassRate } %)` )
746+ }
747+ if ( data . failed > 0 ) {
748+ const failRate = Math . round ( ( data . failed / totalFeatureTests ) * 100 )
749+ parts . push ( `${ output . styles . error ( '✗' ) } Failed: ${ data . failed } (${ failRate } %)` )
750+ }
751+ if ( data . skipped > 0 ) {
752+ const skipRate = Math . round ( ( data . skipped / totalFeatureTests ) * 100 )
753+ parts . push ( `⊘ Pending: ${ data . skipped } (${ skipRate } %)` )
754+ }
755+ parts . push ( `Duration: ${ ms ( featureDuration ) } ` )
756+
757+ output . print ( ` ${ parts . join ( ' | ' ) } ` )
758+ output . print ( )
716759 } )
760+ output . print ( separator )
717761 output . print ( )
718762 }
719763
720764 // Print worker statistics
721765 if ( Object . keys ( testsByWorker ) . length > 1 ) {
722- output . print ( output . styles . bold ( 'Results by Worker:' ) )
766+ output . print ( output . styles . bold ( 'BY WORKER' ) )
767+ output . print ( subSeparator )
723768 Object . entries ( testsByWorker )
724769 . sort ( ( a , b ) => parseInt ( a [ 0 ] ) - parseInt ( b [ 0 ] ) )
725770 . forEach ( ( [ workerIndex , data ] ) => {
726- const totalTests = data . tests . length
727- const passRate = totalTests > 0 ? Math . round ( ( data . passed / totalTests ) * 100 ) : 0
728- const status = data . failed > 0 ? output . styles . error ( '✗' ) : output . styles . success ( '✓' )
729- output . print ( ` ${ status } Worker ${ workerIndex } ` )
730- output . print ( ` Tests: ${ totalTests } | Passed: ${ output . styles . success ( data . passed ) } | Failed: ${ output . styles . error ( data . failed ) } | Pass Rate: ${ passRate } %` )
771+ const totalWorkerTests = data . tests . length
772+ const workerPassRate = totalWorkerTests > 0 ? Math . round ( ( data . passed / totalWorkerTests ) * 100 ) : 0
773+ const workerDuration = data . tests . reduce ( ( acc , test ) => acc + ( test . duration || 0 ) , 0 )
774+
775+ output . print ( `👷 Worker ${ workerIndex } ` )
776+
777+ const parts = [ ` Total: ${ totalWorkerTests } ` ]
778+ if ( data . passed > 0 ) {
779+ parts . push ( `${ output . styles . success ( '✓' ) } Passed: ${ data . passed } (${ workerPassRate } %)` )
780+ }
781+ if ( data . failed > 0 ) {
782+ const failRate = Math . round ( ( data . failed / totalWorkerTests ) * 100 )
783+ parts . push ( `${ output . styles . error ( '✗' ) } Failed: ${ data . failed } (${ failRate } %)` )
784+ }
785+ if ( data . skipped > 0 ) {
786+ const skipRate = Math . round ( ( data . skipped / totalWorkerTests ) * 100 )
787+ parts . push ( `⊘ Pending: ${ data . skipped } (${ skipRate } %)` )
788+ }
789+ parts . push ( `Duration: ${ ms ( workerDuration ) } ` )
790+
791+ output . print ( ` ${ parts . join ( ' | ' ) } ` )
792+ output . print ( )
731793 } )
794+ output . print ( separator )
732795 output . print ( )
733796 }
734797
735- // Print overall metrics using accurate counts from test objects
736- output . print ( output . styles . bold ( 'Overall Metrics:' ) )
737- const passRate = actualTotal > 0 ? Math . round ( ( actualPassed / actualTotal ) * 100 ) : 0
738- const failRate = actualTotal > 0 ? Math . round ( ( actualFailed / actualTotal ) * 100 ) : 0
739- output . print ( ` Total Tests: ${ actualTotal } ` )
740- output . print ( ` Passed: ${ output . styles . success ( actualPassed ) } (${ passRate } %)` )
741- output . print ( ` Failed: ${ output . styles . error ( actualFailed ) } (${ failRate } %)` )
742- output . print ( ` Skipped: ${ actualPending } ` )
743- if ( actualFailedHooks > 0 ) {
744- output . print ( ` Failed Hooks: ${ output . styles . error ( actualFailedHooks ) } ` )
745- }
746- output . print ( ` Duration: ${ ms ( duration ) } ` )
747- output . print ( ` Workers: ${ this . numberOfWorkers } ` )
748- output . print ( ` Strategy: ${ this . isPoolMode ? 'pool' : 'test/suite' } ` )
749- output . print ( )
750-
751- // Print the classic result line with accurate counts
752- output . result ( actualPassed , actualFailed , actualPending , ms ( duration ) , actualFailedHooks )
798+ // Print the classic result line using stats for backward compatibility
799+ output . result ( stats . passes , stats . failures , stats . pending , ms ( duration ) , stats . failedHooks )
753800 }
754801}
755802
0 commit comments