🔷NUnit Reporter
An NUnit (.NET) reporter for M00N Report. Activates with a single [assembly: M00nReport] attribute, auto-detects CI metadata on 7 providers, and - via the optional M00nReport.NUnit.Playwright package - auto-records Page actions as steps and uploads screenshots, video, and traces for failed tests. Verified against the reporter-conformance suite under the real dotnet test host, including a fault-injection baseline.
Features
One [assembly: M00nReport] attribute - no test-runner wiring.
Branch, commit, pipeline, and build metadata auto-populated on 7 CI providers.
Page actions become pw:api steps; screenshot, trace, and video upload on failure.
Each [Retry] attempt is recorded as a separate, numbered execution.
Never fails the run; retries with backoff and a 5-failure circuit breaker.
M00nStep.Run(...) and M00nAttach for files or bytes.
[M00nCaseId(42, ...)] links a test method to an existing case.
AI Setup Prompt
A complete, self-contained prompt for integrating this reporter into an existing NUnit project using an AI assistant. The prompt covers installation, the environment-variable and m00nreport.json configuration forms, manual steps and attachments, case linking, retries, the Playwright layer, a verification checklist, and the most common integration pitfalls.
M00N_API_KEY and supply it as a CI secret; never hard-code it in m00nreport.json.Quick Start
Install the package and set two environment variables. The [assembly: M00nReport] attribute wires itself into the run - there is no [SetUpFixture], ITestEventListener, or runsettings entry to add.
dotnet add package M00nReport.NUnitActivate the reporter
// AssemblyInfo.cs (or any file in the test project)
[assembly: M00nReport.NUnit.M00nReport]bash / zsh
export M00N_SERVER_URL=https://m00nreport.com # or your self-hosted URL
export M00N_API_KEY=m00n_xxxxxxxxxxxxx # your project API key
dotnet testWindows PowerShell
$env:M00N_SERVER_URL = "https://m00nreport.com"
$env:M00N_API_KEY = "m00n_xxxxxxxxxxxxx"
dotnet testdotnet test behaves exactly as it would without it installed.Configuration Reference
Every option can be set two ways. Precedence, highest wins: environment variable > m00nreport.json > built-in default.
| Env var | m00nreport.json key | Default | Description |
|---|---|---|---|
M00N_SERVER_URL | serverUrl | required | M00N Report server URL |
M00N_API_KEY | apiKey | required | Project API key (m00n_...) |
M00N_LAUNCH | launch | Run <date> | Title for this run |
M00N_TAGS | tags | [] | Comma-separated tags (json: an array of strings, or a comma-separated string) |
M00N_ATTRIBUTES | attributes | {} | JSON object of custom run attributes |
M00N_DEBUG | debug | false | Prints a [m00nreport] line to stdout for every HTTP retry attempt and any final exhaustion; silent when off |
serverUrl and apiKey resolve to a value from either source - if neither resolves, the reporter is silently inactive. A missing, unreadable, or malformed m00nreport.json degrades to the default for every field rather than crashing the run; the same applies to a malformed M00N_ATTRIBUTES JSON string, which falls back to {}.m00nreport.json example
Place the file next to the test assembly's build output (the same folder as the compiled .dll) - it is picked up automatically, no wiring needed.
{
"serverUrl": "https://m00nreport.com",
"apiKey": "m00n_xxxxxxxxxxxxx",
"launch": "Nightly Regression",
"tags": ["smoke", "api"],
"attributes": { "environment": "staging" },
"debug": false
}Optional Playwright layer
dotnet add package M00nReport.NUnit.PlaywrightM00nReport.NUnit) so a plain NUnit consumer never pulls in the browser dependency. See Concepts → Playwright Integration below.CI/CD Context Banner
When a run carries CI/CD-related attribute keys - whether auto-detected (see Concepts → CI Auto-Detection below) or passed via M00N_ATTRIBUTES - M00N Report automatically displays them in a dedicated CI context banner at the top of the launch view. Attributes that don't match the keys below are shown as regular attribute badges instead, which is where triggered_by and ci_job_url currently land.
Recognized CI Attribute Keys
| Banner Field | Accepted Keys (case-insensitive) | Example Value |
|---|---|---|
| Pipeline | pipeline, GITHUB_WORKFLOW, CI_PIPELINE_NAME, JOB_NAME | Deploy Production |
| Branch | branch, git_branch, GITHUB_REF, CI_COMMIT_REF_NAME, BRANCH_NAME | main |
| Commit | commit, git_commit, GITHUB_SHA, CI_COMMIT_SHA, GIT_COMMIT | a1b2c3d (truncated to 7 chars) |
| Build # | build_number, GITHUB_RUN_NUMBER, CI_PIPELINE_ID, BUILD_NUMBER | 1234 |
| Build URL | build_url, GITHUB_SERVER_URL, CI_PIPELINE_URL, BUILD_URL | https://github.com/... (clickable) |
| Environment | environment, env, DEPLOY_ENV | staging |
| Trigger | trigger, GITHUB_EVENT_NAME, CI_PIPELINE_SOURCE | push |
Known Limitations
filePath is the namespace-qualified class name, not a source path. NUnit exposes no source file path at runtime, so filePath in every payload is the test's fully-qualified class name (e.g. Acme.Tests.LoginTests) instead of a .cs path - the closest stable analog. This differs from the pytest/Playwright reporters, which report a real file path.[Ignore] test is never reported. NUnit never executes an [Ignore]-attributed test, so the [M00nReport] action never fires for it and no test/start/test/complete is sent - a genuine NUnit framework limitation, not a reporter gap. A runtime skip (Assert.Ignore() or Assert.Inconclusive()) DOES execute, fires the action, and is reported as skipped.Conformance
This reporter targets the M00N Report ingest v2 contract (public OpenAPI document) and is verified against the M00N Report reporter-conformance suite, run under the REAL dotnet test host (VSTest + the NUnit3TestAdapter, not an in-process NUnitLite shortcut): both the normal and fault-injection (injected transient 5xx) baselines pass, all 11 protocol invariants green on the normal run and all 12 (the additional RETRIES_ON_FAILURE check) green on the fault-injection run. The Playwright layer additionally has real-browser proof: the same scenarios run against a live Chromium instance, with pw:api steps, a failure screenshot, and trace/video uploads observed in the session.
As with the pytest reporter, test/start runs through a retrying background worker and test/complete waits for its matching test/start to land before sending, so the fault-injection baseline stays fully green instead of losing test/start records to a single transient 5xx (the gap that keeps the JS Playwright reporter 1.0.10 fault baseline red). Reliably closing run/end under the real host required one addition beyond AppDomain.ProcessExit: the assembly-level [M00nReport] action also finalizes the run from NUnit's own Suite-level teardown hook for the run's root suite, which the host waits on synchronously - finalizing is idempotent, so both triggers firing is harmless.
Concepts
Reference documentation for each subsystem of the reporter: Playwright integration, manual steps and attachments, case linking and retries, CI auto-detection, resilience, and troubleshooting.