gotest.tools/gotestsum@v1.11.0/testjson/summary_test.go (about) 1 package testjson 2 3 import ( 4 "bytes" 5 "io" 6 "strings" 7 "testing" 8 "time" 9 10 "gotest.tools/v3/assert" 11 "gotest.tools/v3/golden" 12 ) 13 14 func TestSummary_String(t *testing.T) { 15 var testcases = []struct { 16 name string 17 summary Summary 18 expected string 19 }{ 20 { 21 name: "none", 22 summary: SummarizeNone, 23 expected: "none", 24 }, 25 { 26 name: "all", 27 summary: SummarizeAll, 28 expected: "skipped,failed,errors,output", 29 }, 30 { 31 name: "one value", 32 summary: SummarizeErrors, 33 expected: "errors", 34 }, 35 { 36 name: "a few values", 37 summary: SummarizeOutput | SummarizeSkipped | SummarizeErrors, 38 expected: "skipped,errors,output", 39 }, 40 } 41 for _, tc := range testcases { 42 t.Run(tc.name, func(t *testing.T) { 43 assert.Equal(t, tc.summary.String(), tc.expected) 44 }) 45 } 46 } 47 48 func TestPrintSummary_NoFailures(t *testing.T) { 49 patchTimeNow(t) 50 51 out := new(bytes.Buffer) 52 start := time.Now() 53 exec := &Execution{ 54 started: start, 55 done: true, 56 packages: map[string]*Package{ 57 "foo": {Total: 12}, 58 "other": {Total: 1}, 59 }, 60 } 61 timeNow = func() time.Time { 62 return start.Add(34123111 * time.Microsecond) 63 } 64 PrintSummary(out, exec, SummarizeAll) 65 66 expected := "\nDONE 13 tests in 34.123s\n" 67 assert.Equal(t, out.String(), expected) 68 } 69 70 func TestPrintSummary_WithFailures(t *testing.T) { 71 patchPkgPathPrefix(t, "example.com") 72 patchTimeNow(t) 73 74 start := time.Now() 75 exec := &Execution{ 76 started: start, 77 done: true, 78 packages: map[string]*Package{ 79 "example.com/project/fs": { 80 Total: 12, 81 Failed: []TestCase{ 82 { 83 Package: "example.com/project/fs", 84 Test: "TestFileDo", 85 Elapsed: 1411 * time.Millisecond, 86 ID: 1, 87 }, 88 { 89 Package: "example.com/project/fs", 90 Test: "TestFileDoError", 91 Elapsed: 12 * time.Millisecond, 92 ID: 2, 93 }, 94 }, 95 output: map[int][]string{ 96 1: multiLine(`=== RUN TestFileDo 97 Some stdout/stderr here 98 --- FAIL: TestFileDo (1.41s) 99 do_test.go:33 assertion failed 100 `), 101 2: multiLine(`=== RUN TestFileDoError 102 --- FAIL: TestFileDoError (0.01s) 103 do_test.go:50 assertion failed: expected nil error, got WHAT! 104 `), 105 0: multiLine("FAIL\n"), 106 }, 107 action: ActionFail, 108 }, 109 "example.com/project/pkg/more": { 110 Total: 1, 111 Failed: []TestCase{ 112 { 113 Package: "example.com/project/pkg/more", 114 Test: "TestAlbatross", 115 Elapsed: 40 * time.Millisecond, 116 ID: 1, 117 }, 118 }, 119 Skipped: []TestCase{ 120 { 121 Package: "example.com/project/pkg/more", 122 Test: "TestOnlySometimes", 123 Elapsed: 0, 124 ID: 2, 125 }, 126 }, 127 output: map[int][]string{ 128 1: multiLine(`=== RUN TestAlbatross 129 --- FAIL: TestAlbatross (0.04s) 130 `), 131 2: multiLine(`=== RUN TestOnlySometimes 132 --- SKIP: TestOnlySometimes (0.00s) 133 good_test.go:27: the skip message 134 `), 135 }, 136 }, 137 "example.com/project/badmain": { 138 action: ActionFail, 139 output: map[int][]string{ 140 0: multiLine("sometimes main can exit 2\n"), 141 }, 142 }, 143 }, 144 errors: []string{ 145 "pkg/file.go:99:12: missing ',' before newline", 146 }, 147 } 148 timeNow = func() time.Time { 149 return start.Add(34123111 * time.Microsecond) 150 } 151 152 t.Run("summarize all", func(t *testing.T) { 153 out := new(bytes.Buffer) 154 PrintSummary(out, exec, SummarizeAll) 155 156 expected := ` 157 === Skipped 158 === SKIP: project/pkg/more TestOnlySometimes (0.00s) 159 good_test.go:27: the skip message 160 161 === Failed 162 === FAIL: project/badmain (0.00s) 163 sometimes main can exit 2 164 165 === FAIL: project/fs TestFileDo (1.41s) 166 Some stdout/stderr here 167 do_test.go:33 assertion failed 168 169 === FAIL: project/fs TestFileDoError (0.01s) 170 do_test.go:50 assertion failed: expected nil error, got WHAT! 171 172 === FAIL: project/pkg/more TestAlbatross (0.04s) 173 174 === Errors 175 pkg/file.go:99:12: missing ',' before newline 176 177 DONE 13 tests, 1 skipped, 4 failures, 1 error in 34.123s 178 ` 179 assert.Equal(t, out.String(), expected) 180 }) 181 182 t.Run("summarize no output", func(t *testing.T) { 183 out := new(bytes.Buffer) 184 PrintSummary(out, exec, SummarizeAll-SummarizeOutput) 185 186 expected := ` 187 === Skipped 188 === SKIP: project/pkg/more TestOnlySometimes (0.00s) 189 190 === Failed 191 === FAIL: project/badmain (0.00s) 192 === FAIL: project/fs TestFileDo (1.41s) 193 === FAIL: project/fs TestFileDoError (0.01s) 194 === FAIL: project/pkg/more TestAlbatross (0.04s) 195 196 === Errors 197 pkg/file.go:99:12: missing ',' before newline 198 199 DONE 13 tests, 1 skipped, 4 failures, 1 error in 34.123s 200 ` 201 assert.Equal(t, out.String(), expected) 202 }) 203 204 t.Run("summarize only errors", func(t *testing.T) { 205 out := new(bytes.Buffer) 206 PrintSummary(out, exec, SummarizeErrors) 207 208 expected := ` 209 === Errors 210 pkg/file.go:99:12: missing ',' before newline 211 212 DONE 13 tests, 1 skipped, 4 failures, 1 error in 34.123s 213 ` 214 assert.Equal(t, out.String(), expected) 215 }) 216 } 217 218 func patchTimeNow(t *testing.T) { 219 timeNow = func() time.Time { 220 return time.Date(2022, 1, 2, 3, 4, 5, 600, time.UTC) 221 } 222 t.Cleanup(func() { 223 timeNow = time.Now 224 }) 225 } 226 227 func multiLine(s string) []string { 228 return strings.SplitAfter(s, "\n") 229 } 230 231 func TestPrintSummary(t *testing.T) { 232 patchTimeNow(t) 233 234 type testCase struct { 235 name string 236 config func(t *testing.T) ScanConfig 237 expectedOut string 238 expected func(t *testing.T, exec *Execution) 239 } 240 241 run := func(t *testing.T, tc testCase) { 242 exec, err := ScanTestOutput(tc.config(t)) 243 assert.NilError(t, err) 244 245 buf := new(bytes.Buffer) 246 PrintSummary(buf, exec, SummarizeAll) 247 golden.Assert(t, buf.String(), tc.expectedOut) 248 249 if tc.expected != nil { 250 tc.expected(t, exec) 251 } 252 } 253 254 testCases := []testCase{ 255 { 256 name: "missing test fail event", 257 config: scanConfigFromGolden("input/go-test-json-missing-test-fail.out"), 258 expectedOut: "summary/missing-test-fail-event", 259 expected: func(t *testing.T, exec *Execution) { 260 for name, pkg := range exec.packages { 261 assert.Equal(t, len(pkg.running), 0, "package %v still had tests in running", name) 262 } 263 }, 264 }, 265 { 266 name: "output attributed to wrong test", 267 config: scanConfigFromGolden("input/go-test-json-misattributed.out"), 268 expectedOut: "summary/misattributed-output", 269 }, 270 { 271 name: "with subtest failures", 272 config: scanConfigFromGolden("input/go-test-json.out"), 273 expectedOut: "summary/root-test-has-subtest-failures", 274 }, 275 { 276 name: "with parallel failures", 277 config: scanConfigFromGolden("input/go-test-json-with-parallel-fails.out"), 278 expectedOut: "summary/parallel-failures", 279 }, 280 { 281 name: "missing skip message", 282 config: scanConfigFromGolden("input/go-test-json-missing-skip-msg.out"), 283 expectedOut: "summary/bug-missing-skip-message", 284 }, 285 { 286 name: "repeated test case", 287 config: func(t *testing.T) ScanConfig { 288 in := golden.Get(t, "input/go-test-json.out") 289 return ScanConfig{ 290 Stdout: io.MultiReader( 291 bytes.NewReader(in), 292 bytes.NewReader(in), 293 bytes.NewReader(in)), 294 } 295 }, 296 expectedOut: "summary/bug-repeated-test-case-output", 297 }, 298 { 299 name: "with rerun id", 300 config: func(t *testing.T) ScanConfig { 301 return ScanConfig{ 302 Stdout: bytes.NewReader(golden.Get(t, "input/go-test-json.out")), 303 RunID: 7, 304 } 305 }, 306 expectedOut: "summary/with-run-id", 307 }, 308 } 309 310 for _, tc := range testCases { 311 t.Run(tc.name, func(t *testing.T) { 312 run(t, tc) 313 }) 314 } 315 } 316 317 func scanConfigFromGolden(filename string) func(t *testing.T) ScanConfig { 318 return func(t *testing.T) ScanConfig { 319 return ScanConfig{Stdout: bytes.NewReader(golden.Get(t, filename))} 320 } 321 }