# Share an xUnit HTML Report — Stop Pasting the .NET Test Summary

Canonical: https://commareports.com/share-xunit-report
Published: 2026-08-31

> xunit.runner.console -html writes one page; dotnet test --logger html does the same. Publish it to Comma for a URL with anchored comments and a revision per run.

# Share an xUnit HTML report

The .NET testing story ends the same way on most teams: a build agent runs
`dotnet test`, a `.trx` lands in an artifact bucket, and the actual failure
gets communicated as a screenshot of a terminal in a chat thread.

xUnit will hand you a real HTML page. The only missing step is somewhere to
put it.

## One command, one file

Through the SDK:

```bash
dotnet test --logger "html;LogFileName=xunit.html"
# → TestResults/xunit.html
```

Or the standalone console runner, which has had an HTML writer forever:

```bash
xunit.console.exe path/to/tests.dll -html xunit.html
```

Both write a self-contained page — styling inlined, no sibling folder. That
matters: publishing is then one request with no asset step.

## Publish it

Drag the file into [the app](https://commareports.com/), or from CI:

```bash
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 TestResults/xunit.html \
        --arg title "xUnit — $GITHUB_SHA" '{title: $title, html: $html}')"
```

One report id per suite. One URL that always shows the latest run, with every
previous run kept as a revision behind it.

## Already producing .trx?

If a pipeline stage downstream consumes the `.trx`, keep it and add HTML
alongside — loggers compose:

```bash
dotnet test \
  --logger "trx;LogFileName=results.trx" \
  --logger "html;LogFileName=xunit.html"
```

The dashboard keeps its machine format; people get a link.

## Publish on failure

```yaml
- name: Publish xUnit report
  if: always()
  run: ./scripts/publish-report.sh
```

Without `if: always()`, `dotnet test`'s non-zero exit skips the publish on
every red build — the only builds where the report has a reader.

## What review adds

- **Anchored threads** on the failing assertion. See
  [commenting on HTML](/comment-on-html).
- **Revisions**, so "was this failing before my change?" is a diff.
- **Access per report** — private, team, domain-gated, or named reviewers.
  See the [sharing model](/docs/sharing).

## Limits

- **Entry HTML: 5 MB.** Assets: 25 MB per file, 250 MB and 500 files total.
- **60 requests/minute per token.**

## Try it

Comma is free — unlimited reports, unlimited commenters, unlimited revision
history.

**[Publish a test report →](https://commareports.com/)**

### Related

- [Share an NUnit report](/share-nunit-report) · [Share a .NET coverage report](/share-dotnet-coverage-report)
- [Share a JUnit report](/share-junit-report) · [Share a TestNG report](/share-testng-report)
- [Publish from CI](/docs/ci) · [Share a coverage report](/share-coverage-report)
