Share a Go test report
Go's testing story is deliberately terminal-shaped. go test ./... prints
ok and moves on, which is correct for the person who ran it and useless
for everyone else.
The two HTML artifacts Go can produce are both genuinely worth reading, and both die on the machine that made them.
The coverage page
This is the one worth sharing:
go test -coverprofile=cover.out ./...
go tool cover -html=cover.out -o coverage.html
coverage.html is a single self-contained file — annotated source,
green for covered, red for not, with a per-file dropdown. That is a far
better artifact than a coverage percentage, because it answers the actual
question: which branch is untested, and does that matter?
The results page
go test has no built-in HTML reporter. The common routes:
# results as a page
go test -json ./... > test.json
go-test-report -f test.json -o report.html
# or JUnit XML for CI-native display
gotestsum --junitfile junit.xml ./...
Both are single files too. See share a JUnit report if your pipeline is already consuming the XML.
Publish it
go test -coverprofile=cover.out ./... || true
go tool cover -html=cover.out -o coverage.html
curl -fsS -X PATCH "https://commareports.com/api/v1/reports/$REPORT_ID" \
-H "Authorization: Bearer $COMMA_API_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -n --rawfile html coverage.html \
--arg title "Coverage — $(git rev-parse --short HEAD)" \
'{title: $title, html: $html}')"
One call, no assets — the single-file shape is what makes this easy. Use a
scoped token (reports:write) from CI secrets and
PATCH a saved report id, so one URL accumulates a revision per run
instead of a new orphan link every build.
The || true matters: a failing test fails the step, and the publish has
to survive it. In GitHub Actions add if: always(). See
publishing from CI and
GitHub Actions HTML reports.
Scripts run inside a sandboxed iframe (allow-scripts, no
allow-same-origin), so the file selector and the source annotation work
at the URL exactly as they do locally.
What the URL buys you
- The PR links the coverage page, so "is this path tested?" is a click rather than a local run.
- Review lands on the code. Select the uncovered branch, leave a thread — "this is the retry path, it needs a test" — and it stays anchored there across runs. See commenting on HTML.
- Revision diffs beat the percentage. Two revisions, one diff, and you see which lines changed coverage rather than watching a number move by a third of a point.
Who can see it
Per report: private, your team, anyone signed in at your domain, or anyone with the link. The coverage page contains your source code, so team or private is the right default for a private repo (domain-gating is Enterprise). See sharing & access control.
Limits
- Entry HTML: 5 MB.
go tool cover -htmlinlines every covered source file, so a large monorepo can exceed that — generate per-module profiles and publish the modules people review. Assets: 25 MB per file, 250 MB and 500 files total. - Scripts run, sandboxed — no same-origin access.
- 60 requests/minute per token.
Try it
Comma is free — unlimited reports, unlimited commenters, unlimited revision history.