66package main
77
88import (
9+ "bufio"
910 "encoding/json"
1011 "errors"
1112 "fmt"
@@ -45,7 +46,7 @@ func main() {
4546 for k , v := range byPackage {
4647 packages = append (packages , k )
4748 sort .Slice (v , func (i , j int ) bool {
48- return v [i ].Test < v [j ].Test
49+ return v [i ].Test . Value () < v [j ].Test . Value ()
4950 })
5051 }
5152
@@ -67,60 +68,58 @@ func min(i, j int) int {
6768 return j
6869}
6970
70- func actionSymbol (d TestRun ) string {
71- switch d .Action {
72- case "pass" :
73- return "✅"
74- case "fail" :
75- return "❌"
76- case "skip" :
77- return "⏭️"
78- default :
79- panic (fmt .Sprintf ("unhandled action: %s" , d .Action ))
80- }
81- }
82-
8371func loadJSON (
8472 testOutputFile string ,
8573 log logr.Logger ,
8674) map [string ][]TestRun {
87- content , err := os .ReadFile (testOutputFile )
75+ file , err := os .Open (testOutputFile )
8876 if err != nil {
8977 log .Error (
9078 err ,
91- "Unable to read file" ,
79+ "Unable to open file" ,
9280 "file" , testOutputFile )
81+ return make (map [string ][]TestRun )
9382 }
83+ defer file .Close ()
9484
95- // Break into individual lines to make error reporting easier
96- lines := strings .Split (string (content ), "\n " )
97-
98- data := make ([]JSONFormat , 0 , len (lines ))
85+ scanner := bufio .NewScanner (file )
86+ factory := newTestRunFactory ()
9987 errCount := 0
100- for row , line := range lines {
88+ row := 0
89+ for scanner .Scan () {
90+ line := scanner .Bytes ()
10191 if len (line ) == 0 {
10292 // Skip empty lines
10393 continue
10494 }
10595
10696 var d JSONFormat
107- err := json .Unmarshal ([] byte ( line ) , & d )
97+ err := json .Unmarshal (line , & d )
10898 if err != nil {
10999 // Write the line to the log so we don't lose the content
100+ text := string (line )
110101 log .Info (
111102 "Unable to parse" ,
112- "line" , line )
103+ "line" , text )
113104
114- if line != "" && ! strings .HasPrefix (line , "FAIL" ) {
105+ if text != "" && ! strings .HasPrefix (text , "FAIL" ) {
115106 // It's a parse failure we care about, write details
116- logError (log , err , row , line )
107+ logError (log , err , row , text )
117108 errCount ++
118109 }
119110
120111 continue
121112 }
122113
123- data = append (data , d )
114+ factory .apply (d )
115+ row ++
116+ }
117+
118+ if err := scanner .Err (); err != nil {
119+ log .Error (
120+ err ,
121+ "Error reading file" ,
122+ "file" , testOutputFile )
124123 }
125124
126125 if errCount > 0 {
@@ -129,43 +128,15 @@ func loadJSON(
129128 "count" , errCount )
130129 }
131130
132- // Track all the test runs
133- testRuns := make (map [string ]* TestRun )
134- for _ , d := range data {
135-
136- // Find (or create) the test run for this item of data
137- testrun , found := testRuns [d .key ()]
138- if ! found {
139- testrun = & TestRun {
140- Package : d .Package ,
141- Test : d .Test ,
142- }
143-
144- testRuns [d .key ()] = testrun
145- }
146-
147- switch d .Action {
148- case "run" :
149- testrun .run (d .Time )
150-
151- case "pause" :
152- testrun .pause (d .Time )
153-
154- case "cont" :
155- testrun .resume (d .Time )
156-
157- case "output" :
158- testrun .output (d .Output )
159-
160- case "pass" , "fail" , "skip" :
161- testrun .complete (d .Action , d .Time )
131+ // package → list of tests
132+ byPackage := make (map [string ][]TestRun )
133+ for pkg , pkgRuns := range factory .testRuns {
134+ var runs []TestRun
135+ for _ , r := range pkgRuns {
136+ runs = append (runs , * r )
162137 }
163- }
164138
165- // package → list of tests
166- byPackage := make (map [string ][]TestRun , len (data ))
167- for _ , v := range testRuns {
168- byPackage [v .Package ] = append (byPackage [v .Package ], * v )
139+ byPackage [pkg ] = runs
169140 }
170141
171142 return byPackage
@@ -182,6 +153,11 @@ func sensitiveRound(d time.Duration) time.Duration {
182153func printSummary (packages []string , byPackage map [string ][]TestRun ) {
183154 fmt .Printf ("## Package Summary\n \n " )
184155
156+ commonPrefix := findCommonPackagePrefix (packages )
157+
158+ fmt .Printf ("| Result | %s | Time |\n " , commonPrefix )
159+ fmt .Printf ("|--------|:---|-----:|\n " )
160+
185161 // output table-of-contents
186162 for _ , pkg := range packages {
187163 tests := byPackage [pkg ]
@@ -195,8 +171,11 @@ func printSummary(packages []string, byPackage map[string][]TestRun) {
195171 totalRuntime += t .RunTime
196172 }
197173
198- overallOutcome := actionSymbol (tests [0 ])
199- fmt .Printf ("* %s `%s` (runtime %s)\n " , overallOutcome , pkg , totalRuntime )
174+ overallOutcome := tests [0 ].actionSymbol ()
175+ shortPkgName := displayNameForPackage (pkg , commonPrefix )
176+ totalRuntime = sensitiveRound (totalRuntime )
177+
178+ fmt .Printf ("| %s | %s | %s |\n " , overallOutcome , shortPkgName , totalRuntime )
200179 }
201180
202181 fmt .Println ()
@@ -210,7 +189,7 @@ func printDetails(packages []string, byPackage map[string][]TestRun) {
210189 for _ , pkg := range packages {
211190 tests := byPackage [pkg ]
212191 // check package-level indicator, which will be first ("" test name):
213- if tests [0 ].Action != "fail" {
192+ if tests [0 ].Action != Failed {
214193 continue // no failed tests, skip
215194 } else {
216195 anyFailed = true
@@ -249,9 +228,9 @@ func printDetails(packages []string, byPackage map[string][]TestRun) {
249228 continue
250229 }
251230
252- fmt .Printf ("#### Test `%s`\n " , test .Test )
231+ fmt .Printf ("#### Test `%s`\n " , test .Test . Value () )
253232
254- if test .Action == "fail" {
233+ if test .Action == Failed {
255234 fmt .Printf ("Failed in %s:\n " , test .RunTime )
256235 } else {
257236 fmt .Printf ("Elapsed %s:\n " , test .RunTime )
@@ -268,7 +247,7 @@ func printDetails(packages []string, byPackage map[string][]TestRun) {
268247
269248 // Output info on stderr, so that test failure isn’t silent on console
270249 // when running `task ci`, and that full logs are available if they get trimmed
271- fmt .Fprintf (os .Stderr , "- Test failed: %s\n " , test .Test )
250+ fmt .Fprintf (os .Stderr , "- Test failed: %s\n " , test .Test . Value () )
272251 fmt .Fprintln (os .Stderr , "=== TEST OUTPUT ===" )
273252 for _ , outputLine := range test .Output {
274253 fmt .Fprint (os .Stderr , outputLine ) // note that line already has newline attached
@@ -280,7 +259,7 @@ func printDetails(packages []string, byPackage map[string][]TestRun) {
280259 }
281260
282261 if ! anyFailed {
283- fmt .Println ("**🎉 All tests passed. 🎉**" )
262+ fmt .Printf ("**🎉 All tests passed. 🎉**\n \n " )
284263 }
285264}
286265
@@ -315,11 +294,19 @@ func printSlowTests(byPackage map[string][]TestRun) {
315294 return allTests [i ].RunTime > allTests [j ].RunTime
316295 })
317296
318- fmt .Println ("| Package | Name | Time |" )
297+ pkgPrefix := allTests [0 ].Package .Value ()
298+ for _ , test := range allTests {
299+ pkgPrefix = commonPrefix (pkgPrefix , test .Package .Value ())
300+ }
301+
302+ pkgPrefix = strings .TrimRight (pkgPrefix , "/" )
303+
304+ fmt .Printf ("| %s | Name | Time |\n " , pkgPrefix )
319305 fmt .Println ("|---------|------|-----:|" )
320306 for i := 0 ; i < min (10 , len (allTests )); i += 1 {
321307 test := allTests [i ]
322- fmt .Printf ("| `%s` | `%s` | %s |\n " , test .Package , test .Test , test .RunTime )
308+ pkg := displayNameForPackage (test .Package .Value (), pkgPrefix )
309+ fmt .Printf ("| `%s` | `%s` | %s |\n " , pkg , test .Test .Value (), test .RunTime )
323310 }
324311}
325312
@@ -366,7 +353,34 @@ func logError(
366353 )
367354}
368355
369- // key returns a unique key for a test run
370- func (d JSONFormat ) key () string {
371- return d .Package + "/" + d .Test
356+ func commonPrefix (
357+ left string ,
358+ right string ,
359+ ) string {
360+ minLen := min (len (left ), len (right ))
361+ i := 0
362+ for i < minLen && left [i ] == right [i ] {
363+ i ++
364+ }
365+
366+ return left [:i ]
367+ }
368+
369+ // findCommonPackagePrefix finds the common prefix of all package names, to shorten display
370+ func findCommonPackagePrefix (packages []string ) string {
371+ prefix := packages [0 ]
372+ for _ , pkg := range packages {
373+ prefix = commonPrefix (prefix , pkg )
374+ }
375+ prefix = strings .TrimRight (prefix , "/" )
376+ return prefix
377+ }
378+
379+ func displayNameForPackage (
380+ pkg string ,
381+ commonPrefix string ,
382+ ) string {
383+ name := strings .TrimPrefix (pkg , commonPrefix )
384+ name = strings .TrimLeft (name , "/" )
385+ return name
372386}
0 commit comments