HomeBloggotestsum: gotestsum vs Go Test and Other Tools for Better Go Test...

gotestsum: gotestsum vs Go Test and Other Tools for Better Go Test Reporting in CI

Author

Date

Category

Use gotestsum when your Go tests run in CI and humans need to read the results. Plain go test is great at running tests. It is less great at making failures easy to spot in a noisy build log. gotestsum keeps the Go tool you already trust, then adds cleaner output, JUnit XML, summaries, and CI friendly reports.

TLDR: gotestsum is a thin wrapper around go test --json, so you still run normal Go tests. The big win is better reporting in CI, especially when many packages run at once. For example, a team with 1,800 tests across 42 packages may cut failure triage from 12 minutes to 3 minutes because failed tests appear in a short summary and in JUnit tabs. Use go test for simple local checks, and use gotestsum for team builds.

Why plain go test starts to hurt

go test ./... is the classic command. It is fast. It is built in. It needs no setup. For small projects, it is usually enough.

Then your repo grows.

You get more packages. More table tests. More parallel tests. More logs. One flaky test dumps 300 lines. A package fails near the top. The build keeps going. Now someone has to scroll through a wall of text like they are hunting for a missing sock.

Honestly, raw go test output can feel rude in CI. It tells the truth, but not always in a helpful order.

Plain go test gives you:

  • Reliable test execution
  • Simple pass or fail status
  • Coverage support
  • JSON output with -json
  • No extra dependency

That is solid. But CI wants more than solid. CI wants scanable output. CI wants reports. CI wants failed test names without the treasure hunt.

smartphone tablet payment terminal and coins on table enterprise solutions investment tools asset management

What gotestsum actually does

gotestsum does not replace the Go test runner. That matters. It runs go test under the hood. It reads the JSON event stream from go test --json. Then it formats the results in a way that is easier for people and CI systems.

A basic command looks like this:

gotestsum -- ./...

The part after -- is passed to go test. So this also works:

gotestsum -- -race -cover ./...

You still use normal Go flags. You still get normal Go behavior. You just get nicer output.

gotestsum vs go test

Here is the simple version.

  • go test: Best for quick local runs and tiny projects.
  • gotestsum: Best for CI logs, reports, and bigger repos.

With go test, failed output may be mixed with package output, logs, and timing lines. With gotestsum, you can choose a cleaner format. You can show package names. You can show test names. You can hide noise until something fails.

For example:

gotestsum --format testname -- ./...

This prints test names in a friendly way. It is much easier to scan when a build fails at 4:57 p.m. and everyone wants to go home.

Another useful option is JUnit output:

gotestsum --junitfile report.xml -- ./...

That file can be uploaded by many CI systems. GitHub Actions, GitLab CI, Jenkins, CircleCI, Buildkite, and others can show test results in their own UI, with failing tests listed in neat rows.

Why JUnit XML matters in CI

JUnit XML sounds old. It is old. It is also everywhere.

CI tools understand it. Dashboards understand it. Test report plugins understand it. That means your Go tests can appear beside Java, Python, or JavaScript tests without special magic.

With JUnit output, you can often see:

  • Which test failed
  • Which package failed
  • How long each test took
  • Error text from the failure
  • Trends over time

This is where gotestsum earns its keep. A failed build should not become a group reading exercise. It should point to the broken test, fast.

black and white analog speedometer dealership analytics lead tracking car sales dashboard

Other Go test reporting tools

gotestsum is not the only option. It is just one of the most practical ones for CI.

go test -json

This is built into Go. It emits test events as JSON. Tools can parse it. You can store it. You can inspect it later.

The awkward part is that raw JSON is not fun for humans. Expect to waste time if your plan is “just read the JSON in the CI log.” That path gets old after one bad build.

go tool test2json

This is part of the Go toolchain. It converts test output to JSON events. It is useful when building custom tooling.

For most teams, it is lower level than needed. You usually want a report, not a weekend project.

go-junit-report

This tool converts Go test output into JUnit XML. It has been used in many CI setups for years.

It is handy. But gotestsum often feels nicer because it handles formatted terminal output and JUnit generation in one flow. Fewer pipes. Fewer little scripts. Fewer “why is this empty?” moments.

gotestfmt

gotestfmt formats go test output for readability. It is nice for cleaner logs. Some teams prefer its style.

gotestsum tends to be stronger when you want a full CI reporting setup, especially with JUnit files and failure summaries.

richgo

richgo adds color to Go test output. It is fun for local development. It makes success feel cheerful and failure look less like gray soup.

In CI, color alone is not enough. You still need structured reports if you want clickable failures and history.

A good CI setup with gotestsum

A practical command may look like this:

gotestsum \
  --format pkgname \
  --junitfile test-results.xml \
  --jsonfile test-results.json \
  -- \
  -race -cover ./...

This does a few useful things:

  • Shows package level output with --format pkgname
  • Creates JUnit XML for your CI test tab
  • Saves JSON for later debugging
  • Runs race detection for safer concurrent code
  • Runs coverage across all packages

If your CI supports artifacts, store test-results.xml and test-results.json. When a flaky test appears again next week, you will be glad you did.

laptop screen displays four button style options figma design markdown document developer handoff 2

When plain go test is still enough

You do not need gotestsum for every command.

Use plain go test when:

  • You are checking one small package
  • You are running tests inside an editor
  • You want zero extra tools
  • You are debugging with very specific flags

This is fine:

go test ./internal/parser

So is this:

go test -run TestParseDate ./internal/parser

Local loops should stay quick. No need to dress every command in a tuxedo.

Where gotestsum shines

gotestsum is best when the output has an audience. That audience may be your team. It may be your release gate. It may be the poor person assigned to fix a red build before lunch.

Use gotestsum when you need:

  • Shorter CI logs
  • Clear failed test summaries
  • JUnit XML reports
  • Saved JSON test events
  • Consistent output across machines

The benefit is not that gotestsum makes tests smarter. It makes results clearer. That is enough to save real time.

Best practice recommendation

Keep both tools.

Use go test for fast local work. Use gotestsum in CI. Add JUnit XML output. Save JSON when builds fail often. Pick a format your team can read in five seconds.

A simple default is:

gotestsum --format testname --junitfile junit.xml -- ./...

If your repo is large, try --format pkgname. If your team wants more detail, try --format standard-verbose. The right choice is the one that makes the next failure obvious.

Final take: go test is the engine. gotestsum is the dashboard. The engine runs the car, but the dashboard tells you what is broken before smoke comes out.

Recent posts