Skip to content

Commit

Permalink
Fix junit.xml to include test timeout stack trace
Browse files Browse the repository at this point in the history
  • Loading branch information
dnephin committed Aug 20, 2023
1 parent 496eb7b commit 2dca110
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 18 deletions.
46 changes: 31 additions & 15 deletions cmd/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"gotest.tools/gotestsum/internal/text"
"gotest.tools/gotestsum/testjson"
"gotest.tools/v3/assert"
"gotest.tools/v3/assert/cmp"
"gotest.tools/v3/env"
"gotest.tools/v3/fs"
"gotest.tools/v3/golden"
Expand Down Expand Up @@ -135,23 +136,38 @@ func TestWriteJunitFile_CreatesDirectory(t *testing.T) {
}

func TestScanTestOutput_TestTimeoutPanicRace(t *testing.T) {
format := testjson.NewEventFormatter(io.Discard, "testname", testjson.FormatOptions{})
run := func(t *testing.T, name string) {
format := testjson.NewEventFormatter(io.Discard, "testname", testjson.FormatOptions{})

source := golden.Get(t, "input/go-test-json-panic-race.out")
cfg := testjson.ScanConfig{
Stdout: bytes.NewReader(source),
Handler: &eventHandler{formatter: format, maxFails: 2},
}
exec, err := testjson.ScanTestOutput(cfg)
assert.NilError(t, err)
source := golden.Get(t, "input/go-test-json-"+name+".out")
cfg := testjson.ScanConfig{
Stdout: bytes.NewReader(source),
Handler: &eventHandler{formatter: format},
}
exec, err := testjson.ScanTestOutput(cfg)
assert.NilError(t, err)

out := new(bytes.Buffer)
testjson.PrintSummary(out, exec, testjson.SummarizeAll)
out := new(bytes.Buffer)
testjson.PrintSummary(out, exec, testjson.SummarizeAll)

actual := text.ProcessLines(t, out, text.OpRemoveSummaryLineElapsedTime)
golden.Assert(t, actual, "expected/test-timeout-panic-race-summary")
actual := text.ProcessLines(t, out, text.OpRemoveSummaryLineElapsedTime)
golden.Assert(t, actual, "expected/"+name+"-summary")

var buf bytes.Buffer
err = junitxml.Write(&buf, exec, junitxml.Config{})
assert.NilError(t, err)
var buf bytes.Buffer
err = junitxml.Write(&buf, exec, junitxml.Config{})
assert.NilError(t, err)

assert.Assert(t, cmp.Contains(buf.String(), "panic: test timed out"))
}

testCases := []string{
"panic-race-1",
"panic-race-2",
}

for _, tc := range testCases {
t.Run(tc, func(t *testing.T) {
run(t, tc)
})
}
}
File renamed without changes.
41 changes: 41 additions & 0 deletions cmd/testdata/expected/panic-race-2-summary
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@

=== Failed
=== FAIL: example (0.00s)
panic: test timed out after 2s
running tests:
TestSleepsTooLong (2s)

goroutine 17 [running]:
testing.(*M).startAlarm.func1()
/usr/lib/go/src/testing/testing.go:2241 +0x3c5
created by time.goFunc
/usr/lib/go/src/time/sleep.go:176 +0x32

goroutine 1 [chan receive]:
testing.(*T).Run(0xc0000076c0, {0x52afd7?, 0x4baa25?}, 0x533d98)
/usr/lib/go/src/testing/testing.go:1630 +0x405
testing.runTests.func1(0x6102c0?)
/usr/lib/go/src/testing/testing.go:2036 +0x45
testing.tRunner(0xc0000076c0, 0xc000096c88)
/usr/lib/go/src/testing/testing.go:1576 +0x10b
testing.runTests(0xc000026140?, {0x606c80, 0x1, 0x1}, {0x0?, 0x100c0000a6598?, 0x60fae0?})
/usr/lib/go/src/testing/testing.go:2034 +0x489
testing.(*M).Run(0xc000026140)
/usr/lib/go/src/testing/testing.go:1906 +0x63a
main.main()
_testmain.go:47 +0x1aa

goroutine 6 [sleep]:
time.Sleep(0x4a817c800)
/usr/lib/go/src/runtime/time.go:195 +0x135
gotest.tools/gotestsum/example.TestSleepsTooLong(0x0?)
/home/daniel/pers/code/gotestsum/example/testing_test.go:9 +0x25
testing.tRunner(0xc000007860, 0x533d98)
/usr/lib/go/src/testing/testing.go:1576 +0x10b
created by testing.(*T).Run
/usr/lib/go/src/testing/testing.go:1629 +0x3ea
FAIL gotest.tools/gotestsum/example 2.003s

=== FAIL: example TestSleepsTooLong (unknown)

DONE 1 tests, 2 failures
38 changes: 38 additions & 0 deletions cmd/testdata/input/go-test-json-panic-race-2.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{"Time":"2023-08-12T12:54:44.132409933-04:00","Action":"start","Package":"gotest.tools/gotestsum/example"}
{"Time":"2023-08-12T12:54:44.133131471-04:00","Action":"run","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong"}
{"Time":"2023-08-12T12:54:44.133140584-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"=== RUN TestSleepsTooLong\n"}
{"Time":"2023-08-12T12:54:46.135570065-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"panic: test timed out after 2s\n"}
{"Time":"2023-08-12T12:54:46.135604434-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"running tests:\n"}
{"Time":"2023-08-12T12:54:46.135608775-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"\tTestSleepsTooLong (2s)\n"}
{"Time":"2023-08-12T12:54:46.135611536-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"\n"}
{"Time":"2023-08-12T12:54:46.135614121-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"goroutine 17 [running]:\n"}
{"Time":"2023-08-12T12:54:46.135643208-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"testing.(*M).startAlarm.func1()\n"}
{"Time":"2023-08-12T12:54:46.135647115-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"\t/usr/lib/go/src/testing/testing.go:2241 +0x3c5\n"}
{"Time":"2023-08-12T12:54:46.135652292-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"created by time.goFunc\n"}
{"Time":"2023-08-12T12:54:46.135655313-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"\t/usr/lib/go/src/time/sleep.go:176 +0x32\n"}
{"Time":"2023-08-12T12:54:46.135657739-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"\n"}
{"Time":"2023-08-12T12:54:46.135660238-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"goroutine 1 [chan receive]:\n"}
{"Time":"2023-08-12T12:54:46.135662906-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"testing.(*T).Run(0xc0000076c0, {0x52afd7?, 0x4baa25?}, 0x533d98)\n"}
{"Time":"2023-08-12T12:54:46.135666381-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"\t/usr/lib/go/src/testing/testing.go:1630 +0x405\n"}
{"Time":"2023-08-12T12:54:46.135668821-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"testing.runTests.func1(0x6102c0?)\n"}
{"Time":"2023-08-12T12:54:46.135671151-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"\t/usr/lib/go/src/testing/testing.go:2036 +0x45\n"}
{"Time":"2023-08-12T12:54:46.135673732-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"testing.tRunner(0xc0000076c0, 0xc000096c88)\n"}
{"Time":"2023-08-12T12:54:46.135676164-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"\t/usr/lib/go/src/testing/testing.go:1576 +0x10b\n"}
{"Time":"2023-08-12T12:54:46.135678759-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"testing.runTests(0xc000026140?, {0x606c80, 0x1, 0x1}, {0x0?, 0x100c0000a6598?, 0x60fae0?})\n"}
{"Time":"2023-08-12T12:54:46.135684642-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"\t/usr/lib/go/src/testing/testing.go:2034 +0x489\n"}
{"Time":"2023-08-12T12:54:46.135687261-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"testing.(*M).Run(0xc000026140)\n"}
{"Time":"2023-08-12T12:54:46.135715549-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"\t/usr/lib/go/src/testing/testing.go:1906 +0x63a\n"}
{"Time":"2023-08-12T12:54:46.135718294-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"main.main()\n"}
{"Time":"2023-08-12T12:54:46.135726996-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"\t_testmain.go:47 +0x1aa\n"}
{"Time":"2023-08-12T12:54:46.135729722-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"\n"}
{"Time":"2023-08-12T12:54:46.135732073-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"goroutine 6 [sleep]:\n"}
{"Time":"2023-08-12T12:54:46.135734314-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"time.Sleep(0x4a817c800)\n"}
{"Time":"2023-08-12T12:54:46.13573659-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"\t/usr/lib/go/src/runtime/time.go:195 +0x135\n"}
{"Time":"2023-08-12T12:54:46.135739011-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"gotest.tools/gotestsum/example.TestSleepsTooLong(0x0?)\n"}
{"Time":"2023-08-12T12:54:46.135760842-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"\t/home/daniel/pers/code/gotestsum/example/testing_test.go:9 +0x25\n"}
{"Time":"2023-08-12T12:54:46.135763588-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"testing.tRunner(0xc000007860, 0x533d98)\n"}
{"Time":"2023-08-12T12:54:46.135766232-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"\t/usr/lib/go/src/testing/testing.go:1576 +0x10b\n"}
{"Time":"2023-08-12T12:54:46.135768744-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"created by testing.(*T).Run\n"}
{"Time":"2023-08-12T12:54:46.135771535-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Test":"TestSleepsTooLong","Output":"\t/usr/lib/go/src/testing/testing.go:1629 +0x3ea\n"}
{"Time":"2023-08-12T12:54:46.135869063-04:00","Action":"output","Package":"gotest.tools/gotestsum/example","Output":"FAIL\tgotest.tools/gotestsum/example\t2.003s\n"}
{"Time":"2023-08-12T12:54:46.135881864-04:00","Action":"fail","Package":"gotest.tools/gotestsum/example","Elapsed":2.003}
11 changes: 8 additions & 3 deletions testjson/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,9 +250,14 @@ func tcIDSet(skipped []TestCase) map[int]struct{} {
return result
}

// TestMainFailed returns true if the package failed, but there were no tests.
// This may occur if the package init() or TestMain exited non-zero.
// TestMainFailed returns true if the package has output related to a failure. This
// may happen if a TestMain or init function panic, or if test timeout
// is reached and output is associated with the package instead of the running
// test.
func (p *Package) TestMainFailed() bool {
if p.testTimeoutPanicInTest != "" {
return true
}
return p.action == ActionFail && len(p.Failed) == 0
}

Expand Down Expand Up @@ -538,7 +543,7 @@ func (e *Execution) Failed() []TestCase {
// Add package-level failure output if there were no failed tests, or
// if the test timeout was reached (because we now have to store that
// output on the package).
if pkg.TestMainFailed() || pkg.testTimeoutPanicInTest != "" {
if pkg.TestMainFailed() {
failed = append(failed, TestCase{Package: name})
}
failed = append(failed, pkg.Failed...)
Expand Down

0 comments on commit 2dca110

Please sign in to comment.