go test -json
go test -json is go test with its output converted to a stream of
JSON events — one object per line — by Go's built-in test2json. Every
line says what happened (Action), in which package, to which test, and
what the test printed. It is the format CI tools, IDEs, gotestsum and
go-junit-report read instead of scraping --- FAIL: lines.
What a line looks like
{"Time":"2026-11-07T10:00:00.12Z","Action":"run","Package":"example.com/shop/cart","Test":"TestCoupon/SAVE10"}
{"Time":"2026-11-07T10:00:00.13Z","Action":"output","Package":"example.com/shop/cart","Test":"TestCoupon/SAVE10","Output":" cart_test.go:42: total = 90.00, want 81.00\n"}
{"Time":"2026-11-07T10:00:00.14Z","Action":"fail","Package":"example.com/shop/cart","Test":"TestCoupon/SAVE10","Elapsed":0.02}
{"Time":"2026-11-07T10:00:00.41Z","Action":"fail","Package":"example.com/shop/cart","Elapsed":0.41}
| Field | Meaning |
|---|---|
Action |
What happened — see the table below |
Package |
The import path of the package under test |
Test |
The test name; absent on package-level events |
Elapsed |
Seconds, on pass, fail and skip |
Output |
One chunk of printed output, newline included |
FailedBuild |
Go 1.24+: on a package fail, the build that broke it |
The actions
| Action | Meaning |
|---|---|
start |
The package's test binary started (Go 1.20+) |
run |
A test started |
pause / cont |
A t.Parallel() test paused, then continued |
output |
The test (or package) printed something |
pass / fail / skip |
Terminal: the test or package finished with that result |
bench |
A benchmark printed its result line |
build-output |
Go 1.24+: compiler output, keyed by ImportPath |
build-fail |
Go 1.24+: that build failed |
A finished test gets exactly one terminal event. A package with no
test files gets a single package-level skip.
The parts that bite
- Parents fail with their subtests.
TestCoupon/SAVE10failing makesTestCouponfail too, so a naive count offailevents double-counts. Subtests are namedParent/child, with spaces turned into underscores. - A panic can leave a test open. When the binary dies mid-test — a
panic in a goroutine,
-timeoutreached,os.Exit— the package getsfailbut the running test may get no terminal event at all. Its last output usually holds thepanic:and stack. A timeout panic lists the tests that were still running. - A package can fail with every test passing. A panic in
TestMain, a race detected after the tests, or a build failure all produce a packagefailwith no failing test. Reports that only list failing tests show a red build and an empty failure list. - Build errors weren't JSON before Go 1.24. Older toolchains print
compiler errors to stderr as plain text. Without
2>&1they vanish from the saved file; with it, the file mixes JSON and text lines, so parsers should skip lines that aren't JSON. - Parallel output interleaves. Events from
t.Parallel()tests arrive mixed together. Group byPackage+Test, never by position in the file. (=== NAMElines inOutputmark the switch.) - Piping hides the exit code.
go test -json ./... | tee test.jsonexits withtee's status, so a failing run looks green. Useset -o pipefail, or write to a file and checkgo test's status. - Cached results are replayed. A cached package re-emits its events
with the original output. Use
-count=1when you need a fresh run.
Getting a readable report
Convert it to JUnit XML for CI test tabs:
gotestsum --junitfile junit.xml -- ./...
go test -json ./... 2>&1 | go-junit-report -parser gojson > junit.xml
Or skip the conversion: the free
JUnit XML viewer reads go test -json
output as-is. Packages become suites, tests and subtests become cases, a
test with no terminal event shows as an error, a package that failed
without a failing test (or failed to build) gets its own entry with the
output, and a test that failed then passed on a re-run is marked
flaky. Copy the Markdown summary into the pull
request, or publish the report as a link.
Try it
Comma is free — unlimited reports, unlimited commenters, unlimited revision history.
Related
- JUnit XML — the format most CI test tabs read
- Test reporter — console, JUnit and HTML outputs per runner
- Go coverprofile — the other file
go testwrites - Share a Go test report · Glossary