@@ -2,11 +2,11 @@ package runner
22
33import (
44 "bufio"
5- "bytes"
65 "encoding/json"
76 "errors"
87 "fmt"
98 "log"
9+ "os"
1010 "os/exec"
1111 "strings"
1212
@@ -27,36 +27,35 @@ type Runner struct {
2727// RunTests executes the tests for each provided package and aggregates all results.
2828// It returns all test results and any error encountered during testing.
2929func (r * Runner ) RunTests () ([]reports.TestResult , error ) {
30- var jsonOutputs [][] byte
30+ var jsonFilePaths []string
3131 packages := r .SelectedTestPackages
3232 if r .RunAllTestPackages {
3333 packages = []string {"./..." }
3434 }
3535
3636 for _ , p := range packages {
3737 for i := 0 ; i < r .RunCount ; i ++ {
38- jsonOutput , passed , err := r .runTests (p )
38+ jsonFilePath , passed , err := r .runTests (p )
3939 if err != nil {
4040 return nil , fmt .Errorf ("failed to run tests in package %s: %w" , p , err )
4141 }
42- jsonOutputs = append (jsonOutputs , jsonOutput )
42+ jsonFilePaths = append (jsonFilePaths , jsonFilePath )
4343 if ! passed && r .FailFast {
4444 break
4545 }
4646 }
4747 }
4848
49- return parseTestResults (jsonOutputs )
49+ return parseTestResults (jsonFilePaths )
5050}
5151
5252type exitCoder interface {
5353 ExitCode () int
5454}
5555
56- // runTestPackage executes the test command for a single test package.
57- // It returns the command output, a boolean indicating success, and any error encountered.
58- func (r * Runner ) runTests (packageName string ) ([]byte , bool , error ) {
59- args := []string {"test" , packageName , "-json" , "-count=1" } // Enable JSON output for parsing
56+ // runTests runs the tests for a given package and returns the path to the output file.
57+ func (r * Runner ) runTests (packageName string ) (string , bool , error ) {
58+ args := []string {"test" , packageName , "-json" , "-count=1" } // Enable JSON output
6059 if r .UseRace {
6160 args = append (args , "-race" )
6261 }
@@ -68,36 +67,47 @@ func (r *Runner) runTests(packageName string) ([]byte, bool, error) {
6867 if r .Verbose {
6968 log .Printf ("Running command: go %s\n " , strings .Join (args , " " ))
7069 }
70+
71+ // Create a temporary file to store the output
72+ tmpFile , err := os .CreateTemp ("" , "test-output-*.json" )
73+ if err != nil {
74+ return "" , false , fmt .Errorf ("failed to create temp file: %w" , err )
75+ }
76+ defer tmpFile .Close ()
77+
78+ // Run the command with output directed to the file
7179 cmd := exec .Command ("go" , args ... )
7280 cmd .Dir = r .ProjectPath
81+ cmd .Stdout = tmpFile
82+ cmd .Stderr = tmpFile
7383
74- var out bytes.Buffer
75- cmd .Stdout = & out
76- cmd .Stderr = & out
77-
78- // Run the command
79- err := cmd .Run ()
84+ err = cmd .Run ()
8085 if err != nil {
8186 var exErr exitCoder
8287 // Check if the error is due to a non-zero exit code
8388 if errors .As (err , & exErr ) && exErr .ExitCode () == 0 {
84- return nil , false , fmt .Errorf ("test command failed at %s: %w" , packageName , err )
89+ return "" , false , fmt .Errorf ("test command failed at %s: %w" , packageName , err )
8590 }
86- return out . Bytes (), false , nil // Test failed
91+ return tmpFile . Name (), false , nil // Test failed
8792 }
8893
89- return out . Bytes (), true , nil // Test succeeded
94+ return tmpFile . Name (), true , nil // Test succeeded
9095}
9196
92- // parseTestResults analyzes multiple JSON outputs from 'go test -json' commands to determine test results.
93- // It accepts a slice of []byte where each []byte represents a separate JSON output from a test run.
94- // This function aggregates results across multiple test runs, summing runs and passes for each test.
95- func parseTestResults (datas [][]byte ) ([]reports.TestResult , error ) {
97+ // parseTestResults reads the test output files and returns the parsed test results.
98+ func parseTestResults (filePaths []string ) ([]reports.TestResult , error ) {
9699 testDetails := make (map [string ]* reports.TestResult ) // Holds run, pass counts, and other details for each test
97100
98- // Process each data set
99- for _ , data := range datas {
100- scanner := bufio .NewScanner (bytes .NewReader (data ))
101+ // Process each file
102+ for _ , filePath := range filePaths {
103+ file , err := os .Open (filePath )
104+ if err != nil {
105+ return nil , fmt .Errorf ("failed to open test output file: %w" , err )
106+ }
107+ defer os .Remove (filePath ) // Clean up file after parsing
108+ defer file .Close ()
109+
110+ scanner := bufio .NewScanner (file )
101111 for scanner .Scan () {
102112 var entry struct {
103113 Action string `json:"Action"`
@@ -146,7 +156,7 @@ func parseTestResults(datas [][]byte) ([]reports.TestResult, error) {
146156 }
147157
148158 if err := scanner .Err (); err != nil {
149- return nil , fmt .Errorf ("reading standard input : %w" , err )
159+ return nil , fmt .Errorf ("reading test output file : %w" , err )
150160 }
151161 }
152162
0 commit comments