Share a Catch2 report
The reason people choose Catch2 is that its failures explain themselves:
tests/buffer.cpp:214: FAILED:
REQUIRE( buf.read_u32(offset) == expected )
with expansion:
3735928559 == 3405691582
That with expansion block is expression decomposition, and it is the single
most useful thing in a C++ test framework. It is also the first casualty of
every summarised report — a pass/fail count tells you a test broke, and Catch2
already told you exactly how.
Catch2 has no HTML reporter, so getting that detail to a colleague takes one conversion step.
Pick a reporter
# widest tool support
./tests --reporter junit --out results.xml
# richer: keeps section nesting and full expression detail
./tests --reporter xml --out results.xml
# multiple at once (Catch2 v3)
./tests --reporter junit::out=results.xml --reporter console::out=-
That last form is worth knowing: v3 lets you emit machine-readable XML and keep human-readable console output in the same run, so the CI log stays useful while the artifact gets produced.
Convert and publish
npx xunit-viewer --results=results.xml --output=report.html
# or
pip install junit2html && junit2html results.xml report.html
Drag report.html into the app, or POST it:
curl -fsS -X POST "https://commareports.com/api/v1/reports" \
-H "Authorization: Bearer $COMMA_API_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -n --rawfile html report.html \
--arg t "Catch2 — libcore @ $(git rev-parse --short HEAD)" \
'{title: $t, html: $html}')"
Check the rendered output for the expansion block before you send the link.
Some JUnit converters drop the failure message body in favour of the type
attribute; if yours does, switch to Catch2's xml reporter and a converter that
reads it, because without the expansion the report is much less useful than the
console output it replaced.
Sections and scenarios
Catch2's SECTION mechanism re-runs the test body once per leaf, so a single TEST_CASE can produce a dozen result rows that share a name. In BDD form:
SCENARIO("buffer handles unaligned reads") {
GIVEN("a buffer with a two-byte header") {
WHEN("reading a u32 at offset 1") {
THEN("the value is byte-swapped correctly") { … }
}
}
}
A converter that preserves nesting renders that as the tree it was written as. A converter that flattens it produces twelve rows called "buffer handles unaligned reads", which is worse than useless in a shared report — publish a sample and look at it before wiring this into CI.
From CI
./tests --reporter junit --out results.xml || TESTS_FAILED=1
npx xunit-viewer --results=results.xml --output=report.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 report.html \
--arg t "Catch2 — $TOOLCHAIN @ $GITHUB_SHA" '{title: $t, html: $html}')"
exit "${TESTS_FAILED:-0}"
Publish before exiting, with if: always() / when: always / post { always }
so a failing build still leaves the report behind. One report id per toolchain
gives each configuration a stable URL and its own revision history.
What review adds
- Anchored threads on the failing case — see commenting on HTML.
- Revisions, so an intermittent failure has a record.
- Access per report — private, team, domain-gated or named reviewers. See the sharing model.
Limits
- Entry HTML: 5 MB.
- 60 requests/minute per token.
Try it
Comma is free — unlimited reports, unlimited commenters, unlimited revision history.