M00nReport.NUnit.Playwright
1.1.0
dotnet add package M00nReport.NUnit.Playwright --version 1.1.0
NuGet\Install-Package M00nReport.NUnit.Playwright -Version 1.1.0
<PackageReference Include="M00nReport.NUnit.Playwright" Version="1.1.0" />
<PackageVersion Include="M00nReport.NUnit.Playwright" Version="1.1.0" />
<PackageReference Include="M00nReport.NUnit.Playwright" />
paket add M00nReport.NUnit.Playwright --version 1.1.0
#r "nuget: M00nReport.NUnit.Playwright, 1.1.0"
#:package M00nReport.NUnit.Playwright@1.1.0
#addin nuget:?package=M00nReport.NUnit.Playwright&version=1.1.0
#tool nuget:?package=M00nReport.NUnit.Playwright&version=1.1.0
M00nReport for NUnit
Official NUnit reporter for M00N Report, an AI-native test management platform. Results, steps, retries and attachments land in M00N Report while the run is still executing, and each test can carry the manual test case it covers. A reporting problem disables the reporter and leaves the tests alone; it never fails your run.
Which package
Three packages ship from this repository.
| Package | Install it | Targets |
|---|---|---|
| M00nReport.NUnit | Always. This is the reporter. | netstandard2.0 + net8.0 |
| M00nReport.NUnit.Playwright | Only if your tests drive Playwright. | net8.0 only |
| M00nReport.Client | Never directly. It arrives transitively. | netstandard2.0 + net8.0 |
The core package runs on .NET Framework 4.6.1 and newer as well as modern .NET. M00nReport.NUnit.Playwright is net8.0 only, because Microsoft.Playwright.NUnit is, so a .NET Framework project installs the core package alone.
You also need NUnit 3.13.3 or newer, and NUnit3TestAdapter in the test project so dotnet test discovers your tests at all.
Installation
dotnet add package M00nReport.NUnit
# only if your tests drive Playwright
dotnet add package M00nReport.NUnit.Playwright
Quick Start
1. Get your API key
In M00N Report, open Project Settings → API Keys and copy the key. It starts with m00n_, and it identifies both the organization and the project.
Keep it out of the repository. In CI it belongs in a secret; locally, in an environment variable.
2. Switch the reporter on
One attribute, anywhere in the test assembly:
using M00nReport.NUnit;
[assembly: M00nReport]
Then point it at your project:
$env:M00N_SERVER_URL = "https://m00nreport.com" # or your own instance, root origin, no /api
$env:M00N_API_KEY = "m00n_..."
export M00N_SERVER_URL=https://m00nreport.com
export M00N_API_KEY=m00n_...
3. Run your tests, and check it worked
dotnet test
The reporter prints a run id when it connects and a summary when it finishes, but dotnet test shows neither at its default verbosity. To see them:
dotnet test --logger "console;verbosity=detailed"
[m00nreport] Run started: run-8f2c1a...
============================================================
[m00nreport] Run Summary
------------------------------------------------------------
Run ID: run-8f2c1a...
Tests: 2/2 sent
============================================================
The other confirmation is the app: open the project's Launches list and the run is there, filling in as tests finish. If it is not, see Troubleshooting.
Configuration
Resolution order per field, highest wins: environment variable > m00nreport.json > default.
| Env var | m00nreport.json |
Default | Description |
|---|---|---|---|
M00N_SERVER_URL |
serverUrl |
required | Your M00N Report 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 |
M00N_ATTRIBUTES |
attributes |
{} |
JSON object of custom run attributes |
M00N_ATTRIBUTE_<NAME> |
- | - | One attribute per variable. M00N_ATTRIBUTE_BRANCH=main becomes branch. Overrides M00N_ATTRIBUTES and CI detection. |
M00N_DEBUG |
debug |
false |
Print every HTTP retry and any final give-up. dotnet test hides it unless you add --logger "console;verbosity=detailed". |
M00N_VIDEO |
video |
false |
Upload the Playwright video on failure, with M00nPageTest |
M00N_TRACING |
tracing |
false |
Upload the Playwright trace on failure, with M00nPageTest |
M00N_VIDEO and M00N_TRACING accept Playwright's own spellings: on, 1, true, yes, retain-on-failure. A malformed value degrades to the default for that field and never throws.
m00nreport.json must sit beside the built test assembly, not beside the csproj, so it needs a copy rule:
<ItemGroup>
<None Update="m00nreport.json" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
Put project defaults there. Never the key.
CI Auto-Detection
Running in GitHub Actions, GitLab CI, Jenkins, Bitbucket Pipelines, Azure DevOps, CircleCI or Travis CI needs no configuration: branch, commit, pipeline, build number, build URL, trigger and who triggered it are attached to the run, taking whichever of those the provider exposes. branch and triggered_by lead the launch card. Anything you set in M00N_ATTRIBUTES or M00N_ATTRIBUTE_<NAME> overrides a detected value.
# .github/workflows/tests.yml
- run: dotnet test
env:
M00N_SERVER_URL: https://m00nreport.com
M00N_API_KEY: ${{ secrets.M00N_API_KEY }}
Steps
M00nStep.Run("Add item to cart", () => cart.Add("A-1"));
var total = M00nStep.Run("Read total", () => cart.Total());
await M00nStep.RunAsync("Submit payment", async () =>
{
await checkout.SubmitAsync();
});
Steps nest, and their timings are recorded. Both overloads have a generic form that returns the body's value, so a step never forces you to restructure a test.
Attachments
M00nAttach.Bytes(pngBytes, "checkout-form.png", "image/png");
M00nAttach.File("artifacts/response.json");
File guesses the content type from the extension (.png, .jpg, .jpeg, .zip, .webm, .txt, .json; anything else is sent as application/octet-stream). Bytes sends application/octet-stream unless you pass one.
A single file over 200 MB is skipped with a warning, and each run has an attachment budget set by your plan. Neither ever fails the test.
Linking Tests to Cases
[Test]
[M00nCaseId(42, "payments", "smoke")]
public void Checkout_rejects_an_expired_card()
{
...
}
The number is the case's internal id, not the TC-42 shown in the UI. Open the case in M00N Report and take the id from the address bar. Trailing strings are per-test tags, on top of the run-level M00N_TAGS.
Playwright Integration
Derive from M00nPageTest instead of Playwright's PageTest and every page action becomes a step in the report, with its selector and timing. A failing test uploads screenshot.png with no configuration at all.
using M00nReport.NUnit.Playwright;
public class LoginTests : M00nPageTest
{
[Test]
public async Task Login_succeeds_with_valid_credentials()
{
await Page.GotoAsync("https://example.com/login"); // each becomes a step
await Page.FillAsync("#email", "user@example.com");
await Page.ClickAsync("button[type=submit]");
}
}
Set M00N_VIDEO or M00N_TRACING to upload those artifacts as well. Both upload on failure only, so a green suite producing no video is the intended behaviour rather than a fault.
Retries
NUnit's own [Retry(n)] works unchanged, and every attempt is reported rather than only the final verdict, so a flaky test is visible as flaky rather than as a pass.
[Test]
[Retry(3)]
public void Flaky_under_load() { ... }
What Gets Sent
To your server URL over HTTPS: test names and fixture names, step names and timings, outcomes, exception messages and stack traces, the CI attributes above, and whatever you pass to M00nAttach.
Not sent: your source code, and no environment variables beyond the CI attributes above and any M00N_ATTRIBUTE_<NAME> you set yourself. The API key is never printed, including under M00N_DEBUG.
Troubleshooting
Every message below goes to stderr, prefixed [m00nreport], and the run stays green in all of them. dotnet test shows these at default verbosity; the run id and the summary need --logger "console;verbosity=detailed".
| Message | Cause |
|---|---|
Server unavailable (<url>). Reporter disabled - tests will continue without reporting. |
A wrong URL, or the host is unreachable from the test machine. |
<reason>. Reporter disabled. |
The server refused the run at startup. A rejected API key reads Unauthorized. Reporter disabled. |
<reason>. Reporter disabled for this run. |
The server answered, but not with a run id, and the failure was not a permanent one. |
Reporter disabled: <error> |
The reporter could not start at all, most often a server URL that cannot be parsed. |
The server did not answer (<reason>). Retrying with a shorter timeout; reporting stops after 5 consecutive failures. |
The first failed call after a working start. Later attempts get a much shorter timeout. |
Multiple service failures detected. Disabling reporter for remaining tests. |
Five consecutive failures. The tests already reported are kept. |
The server refused a test result (<reason>). Later refusals are not repeated; the run summary carries the count. |
The server rejected the payload. The summary's Refused: line says how many, and none of those are in the dashboard. |
Attachment not stored: "<name>" (<code>). Further attachments for this run may be lost the same way. |
Usually a run that was stopped from the UI (RUN_NOT_ACTIVE). |
Attachment skipped: "<name>" (<n>MB) exceeds 200MB limit. |
One file over the per-file cap. The rest of the run is unaffected. |
[M00nReport] is applied more than once for the same test |
The attribute is on both the assembly and a class. Keep the assembly one. |
| Nothing at all, and no run in the app | Neither variable resolved, so the reporter stayed silently inactive. In CI this is most often a forked pull request: GitHub does not expose secrets to them, so the secret is an empty string. |
M00N_DEBUG=true distinguishes "never tried" from "tried and could not reach the server". Its output goes through the same channel as the run id, so it needs the detailed logger too.
Known Limitations
dotnet testhides the reporter's output by default. The run id and the end-of-run summary are printed, but the console logger only shows them at--logger "console;verbosity=detailed", so a working run and an inactive reporter look alike in the console.m00nreport.jsonis read from the output directory. Without the copy rule above, dropping the file beside the csproj does nothing and is silent.- Runs are not linked to releases. The reporter reports a launch; attaching launches to a release is done in the app or over MCP.
Support
License
MIT License. See LICENSE.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- M00nReport.NUnit (>= 1.1.0)
- Microsoft.Playwright.NUnit (>= 1.61.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.