@@ -736,43 +736,67 @@ func prettyProjectPath(projectPath string) (string, error) {
736736}
737737
738738func (r * Runner ) rerunFailedTests (results []reports.TestResult ) ([]reports.TestResult , error ) {
739- var failingTests []reports.TestResult
739+ // Group failing tests by package for more efficient reruns
740+ failingTestsByPackage := make (map [string ][]string )
740741 for _ , tr := range results {
741742 if ! tr .Skipped && tr .PassRatio < 1 {
742- failingTests = append (failingTests , tr )
743+ if _ , exists := failingTestsByPackage [tr .TestPackage ]; ! exists {
744+ failingTestsByPackage [tr .TestPackage ] = []string {}
745+ }
746+ failingTestsByPackage [tr .TestPackage ] = append (failingTestsByPackage [tr .TestPackage ], tr .TestName )
743747 }
744748 }
745749
746750 if r .Verbose {
747- log .Info ().Msgf ("Rerunning failing tests: %v" , failingTests )
751+ log .Info ().Msgf ("Rerunning failing tests grouped by package : %v" , failingTestsByPackage )
748752 }
749753
750- var rerunResults []reports. TestResult
754+ var rerunJsonFilePaths []string
751755
752- // Rerun each failing test up to RerunFailed times
756+ // Rerun each failing test package up to RerunFailed times
753757 for i := 0 ; i < r .RerunFailed ; i ++ {
754- for _ , fTest := range failingTests {
755- testCmd := r .buildGoTestCommandForTest (fTest )
756-
757- if r .Verbose {
758- log .Info ().Msgf ("Rerun iteration %d for %s: %v" , i + 1 , fTest .TestName , testCmd )
758+ for pkg , tests := range failingTestsByPackage {
759+ // Build regex pattern to match all failing tests in this package
760+ testPattern := fmt .Sprintf ("^(%s)$" , strings .Join (tests , "|" ))
761+
762+ cmd := []string {
763+ "go" , "test" ,
764+ pkg ,
765+ "-run" , testPattern ,
766+ "-json" ,
759767 }
760768
761- jsonFilePath , _ , err := r .runCmd (testCmd , i )
762- if err != nil {
763- return nil , fmt .Errorf ("error on rerunCmd for test %s: %w" , fTest .TestName , err )
769+ // Add other test flags
770+ if r .UseRace {
771+ cmd = append (cmd , "-race" )
772+ }
773+ if r .Timeout > 0 {
774+ cmd = append (cmd , fmt .Sprintf ("-timeout=%s" , r .Timeout .String ()))
775+ }
776+ if len (r .Tags ) > 0 {
777+ cmd = append (cmd , fmt .Sprintf ("-tags=%s" , strings .Join (r .Tags , "," )))
778+ }
779+ if r .Verbose {
780+ cmd = append (cmd , "-v" )
781+ log .Info ().Msgf ("Rerun iteration %d for package %s: %v" , i + 1 , pkg , cmd )
764782 }
765783
766- additionalResults , err := r .parseTestResults ([]string {jsonFilePath }, "rerun" )
784+ // Run the package tests
785+ jsonFilePath , _ , err := r .runCmd (cmd , i )
767786 if err != nil {
768- return nil , fmt .Errorf ("failed to parse rerun results : %w" , err )
787+ return nil , fmt .Errorf ("error on rerunCmd for package %s : %w" , pkg , err )
769788 }
770789
771- // Collect these rerun results in a slice; we'll merge them later.
772- rerunResults = append (rerunResults , additionalResults ... )
790+ rerunJsonFilePaths = append (rerunJsonFilePaths , jsonFilePath )
773791 }
774792 }
775793
794+ // Parse all rerun results at once with a consistent prefix
795+ rerunResults , err := r .parseTestResults (rerunJsonFilePaths , "rerun" )
796+ if err != nil {
797+ return nil , fmt .Errorf ("failed to parse rerun results: %w" , err )
798+ }
799+
776800 return rerunResults , nil
777801}
778802
@@ -796,7 +820,6 @@ func (r *Runner) buildGoTestCommandForTest(t reports.TestResult) []string {
796820 return cmd
797821}
798822
799- // mergeTestResults merges additional test results into the existing results slice.
800823// mergeTestResults merges additional test results into the existing results slice.
801824func mergeTestResults (mainResults * []reports.TestResult , additional []reports.TestResult ) {
802825 for _ , add := range additional {
@@ -809,30 +832,60 @@ func mergeTestResults(mainResults *[]reports.TestResult, additional []reports.Te
809832 (* mainResults )[i ].Failures += add .Failures
810833 (* mainResults )[i ].Skips += add .Skips
811834
835+ // Merge boolean flags (using OR operation)
836+ (* mainResults )[i ].Panic = (* mainResults )[i ].Panic || add .Panic
837+ (* mainResults )[i ].Race = (* mainResults )[i ].Race || add .Race
838+ (* mainResults )[i ].Timeout = (* mainResults )[i ].Timeout || add .Timeout
839+ (* mainResults )[i ].Skipped = (* mainResults )[i ].Skipped || add .Skipped
840+ (* mainResults )[i ].PackagePanic = (* mainResults )[i ].PackagePanic || add .PackagePanic
841+
812842 // Merge durations
813843 (* mainResults )[i ].Durations = append ((* mainResults )[i ].Durations , add .Durations ... )
814844
845+ // Merge maps for Outputs
846+ if (* mainResults )[i ].Outputs == nil {
847+ (* mainResults )[i ].Outputs = make (map [string ][]string )
848+ }
849+ for runID , outputs := range add .Outputs {
850+ if existing , ok := (* mainResults )[i ].Outputs [runID ]; ok {
851+ (* mainResults )[i ].Outputs [runID ] = append (existing , outputs ... )
852+ } else {
853+ (* mainResults )[i ].Outputs [runID ] = outputs
854+ }
855+ }
856+
815857 // Merge maps for PassedOutputs
816858 if (* mainResults )[i ].PassedOutputs == nil {
817859 (* mainResults )[i ].PassedOutputs = make (map [string ][]string )
818860 }
819861 for runID , outputs := range add .PassedOutputs {
820- (* mainResults )[i ].PassedOutputs [runID ] = append ((* mainResults )[i ].PassedOutputs [runID ], outputs ... )
862+ if existing , ok := (* mainResults )[i ].PassedOutputs [runID ]; ok {
863+ (* mainResults )[i ].PassedOutputs [runID ] = append (existing , outputs ... )
864+ } else {
865+ (* mainResults )[i ].PassedOutputs [runID ] = outputs
866+ }
821867 }
822868
823869 // Merge maps for FailedOutputs
824870 if (* mainResults )[i ].FailedOutputs == nil {
825871 (* mainResults )[i ].FailedOutputs = make (map [string ][]string )
826872 }
827873 for runID , outputs := range add .FailedOutputs {
828- (* mainResults )[i ].FailedOutputs [runID ] = append ((* mainResults )[i ].FailedOutputs [runID ], outputs ... )
874+ if existing , ok := (* mainResults )[i ].FailedOutputs [runID ]; ok {
875+ (* mainResults )[i ].FailedOutputs [runID ] = append (existing , outputs ... )
876+ } else {
877+ (* mainResults )[i ].FailedOutputs [runID ] = outputs
878+ }
829879 }
830880
831- // Update pass ratio
881+ // Merge PackageOutputs
882+ (* mainResults )[i ].PackageOutputs = append ((* mainResults )[i ].PackageOutputs , add .PackageOutputs ... )
883+
884+ // Update pass ratio (consistent with parseTestResults default)
832885 if (* mainResults )[i ].Runs > 0 {
833886 (* mainResults )[i ].PassRatio = float64 ((* mainResults )[i ].Successes ) / float64 ((* mainResults )[i ].Runs )
834887 } else {
835- (* mainResults )[i ].PassRatio = - 1.0
888+ (* mainResults )[i ].PassRatio = 1.0 // Default to 1.0 if no runs
836889 }
837890
838891 found = true
0 commit comments