# Share an NUnit HTML Report — A URL Instead of TestResult.xml

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

> NUnit writes TestResult.xml; the HTML comes from a logger or ReportUnit. Publish it to Comma for a link teammates can open and comment on, with a revision per run.

# Share an NUnit HTML report

NUnit's native output is `TestResult.xml` — a complete, faithful record of the
run that no human has ever voluntarily read. Every team eventually converts it
into something browsable, and then discovers the converted thing lives on a
build agent that recycles in an hour.

## Get one HTML file

The shortest path, if you run through `dotnet test`:

```bash
dotnet test --logger "html;LogFileName=nunit.html"
# → TestResults/nunit.html   (self-contained: CSS inlined, no asset folder)
```

Or convert the XML you already have:

```bash
# ReportUnit — TestResult.xml → a browsable HTML summary
reportunit TestResult.xml nunit.html
```

Either way you end up with one file, which is the easiest possible thing to
publish.

## Publish it

Drag `nunit.html` into [the app](https://commareports.com/), or from a
pipeline:

```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/nunit.html \
        --arg title "NUnit — $BUILD_BUILDNUMBER" '{title: $title, html: $html}')"
```

Because the logger's page is self-contained, there is nothing else to upload —
no `assets/`, no rewrite step. PATCH the same report id on every run and the
suite keeps one stable URL with a revision per run behind it.

## Publish red runs too

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

`dotnet test` exits non-zero when a test fails, so a publish step without
`if: always()` silently skips itself on precisely the runs worth reading.
Azure Pipelines wants `condition: always()`; Jenkins wants
`post { always { … } }`.

## What review adds

- **Anchored threads** on the failing test — "this one is environment-dependent,
  it needs the fixture reset". See [commenting on HTML](/comment-on-html).
- **Revisions**, so a flake's history is a record rather than a memory.
- **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 xUnit report](/share-xunit-report) · [Share a .NET coverage report](/share-dotnet-coverage-report)
- [Share a TestNG report](/share-testng-report) · [Share an Extent report](/share-extent-report)
- [Publish from CI](/docs/ci) · [Share a JUnit report](/share-junit-report)
