NUnit
Set up NUnit for .NET testing and integrate test results with TestKase.
Overview
NUnit is the most popular unit testing framework for .NET applications. It provides a rich set of assertions, parameterized tests, setup/teardown lifecycle hooks, and category-based test filtering. NUnit 3 is the current major version and produces a well-defined XML output format.
To integrate NUnit results with TestKase, generate NUnit 3 XML output and report with --format nunit.
Prerequisites
- .NET SDK 6.0+ (or .NET 8.0+ recommended)
Installation
New Project
Create a new NUnit test project using the built-in template:
dotnet new nunit -n MyProject.TestsThis scaffolds a project with all required NUnit packages pre-configured.
Existing Project
Add NUnit packages to an existing test project:
dotnet add package NUnit
dotnet add package NUnit3TestAdapter
dotnet add package Microsoft.NET.Test.SdkFor NUnit XML output, also install the logger:
dotnet add package NunitXml.TestLoggerProject Setup
Your .csproj file should include these package references:
<!-- MyProject.Tests.csproj -->
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
<PackageReference Include="NUnit" Version="4.1.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
<PackageReference Include="NunitXml.TestLogger" Version="3.1.20" />
</ItemGroup>
</Project>Directory Structure
MyProject.Tests/
MyProject.Tests.csproj
LoginTests.cs
DashboardTests.cs
Helpers/
TestData.csWriting Tests
Create a test file (e.g., LoginTests.cs):
// LoginTests.cs
using NUnit.Framework;
namespace MyProject.Tests
{
[TestFixture]
public class LoginTests
{
private LoginService _loginService;
[SetUp]
public void SetUp()
{
_loginService = new LoginService();
}
[TearDown]
public void TearDown()
{
_loginService = null;
}
[Test, Description("[48271] ValidLogin")]
public void ValidLogin()
{
var result = _loginService.Login("user@example.com", "password123");
Assert.That(result.Success, Is.True);
Assert.That(result.Token, Is.Not.Null);
}
[Test, Description("[48272] InvalidPassword")]
public void InvalidPassword()
{
var result = _loginService.Login("user@example.com", "wrong");
Assert.That(result.Success, Is.False);
Assert.That(result.Error, Is.EqualTo("Invalid credentials"));
}
[Test, Description("[48273] EmptyEmailThrowsException")]
public void EmptyEmailThrowsException()
{
Assert.That(
() => _loginService.Login("", "password123"),
Throws.ArgumentException.With.Message.Contains("Email is required")
);
}
[TestCase("user@example.com", "password123", true)]
[TestCase("admin@example.com", "admin456", true)]
[TestCase("unknown@example.com", "wrong", false)]
[Description("[48274] LoginWithMultipleUsers")]
public void LoginWithMultipleUsers(string email, string password, bool expected)
{
var result = _loginService.Login(email, password);
Assert.That(result.Success, Is.EqualTo(expected));
}
}
}Each test includes a 5-digit Automation ID in its [Description] attribute using square brackets.
The @testkase/reporter CLI extracts these IDs using the regex \[(\d{5})\]. For the example above:
48271→ linked to the "valid login" test case in TestKase48272→ linked to the "invalid password" test case in TestKase48273→ linked to the "empty email" test case in TestKase48274→ linked to the "multiple users" test case in TestKase
Generate Automation IDs in TestKase first, then embed them in your [Description] attributes.
The [XXXXX] pattern can appear anywhere in the description string.
Running Tests
Run all tests:
dotnet testRun with verbose output:
dotnet test --verbosity normalGenerating NUnit XML Output
Use the NUnit XML logger to produce NUnit 3 format output:
dotnet test --logger "nunit;LogFileName=nunit-results.xml" --results-directory test-resultsThis writes the results to test-results/nunit-results.xml.
You can add the logger configuration to a .runsettings file or pass it as a command-line argument.
The --results-directory flag controls where the output file is written.
TestKase Integration
After generating the NUnit XML file, report results to TestKase:
npx @testkase/reporter report \
--token $TESTKASE_PAT \
--project-id PRJ-1 \
--org-id 1173 \
--cycle-id TCYCLE-5 \
--format nunit \
--results-file test-results/nunit-results.xml--cycle-id is optional. If not provided, results are reported to TCYCLE-1 — the master test cycle for the project.
Automation ID Mapping
The reporter extracts 5-digit Automation IDs from NUnit test descriptions using the [XXXXX] bracket pattern:
| Test Pattern | Where to Embed the ID | Extracted ID |
|---|---|---|
| Standard test | [Test, Description("[48271] ValidLogin")] | 48271 |
Parameterized with [TestCase] | [Description("[48274] LoginWithMultipleUsers")] | 48274 |
| Nested namespace | [Test, Description("[48275] ValidateToken")] | 48275 |
The [XXXXX] pattern can appear anywhere in the [Description] attribute. For parameterized tests,
all parameter variations share the same Automation ID.
Complete Example
1. Test File
// LoginTests.cs
using NUnit.Framework;
namespace MyProject.Tests
{
[TestFixture]
public class LoginTests
{
private LoginService _loginService;
[SetUp]
public void SetUp()
{
_loginService = new LoginService();
}
[Test, Description("[48271] ValidLogin")]
public void ValidLogin()
{
var result = _loginService.Login("user@example.com", "password123");
Assert.That(result.Success, Is.True);
}
[Test, Description("[48272] InvalidPassword")]
public void InvalidPassword()
{
var result = _loginService.Login("user@example.com", "wrong");
Assert.That(result.Success, Is.False);
}
}
}2. Run Tests and Generate NUnit XML
dotnet test --logger "nunit;LogFileName=nunit-results.xml" --results-directory test-results3. Report Results to TestKase
npx @testkase/reporter report \
--token $TESTKASE_PAT \
--project-id PRJ-1 \
--org-id 1173 \
--cycle-id TCYCLE-5 \
--format nunit \
--results-file test-results/nunit-results.xmlTroubleshooting
NUnit logger not found
If you get an error like The test logger 'nunit' was not found, the NunitXml.TestLogger package is
not installed. Add it to your project:
dotnet add package NunitXml.TestLoggerAfter installing, rebuild and run again:
dotnet build
dotnet test --logger "nunit;LogFileName=nunit-results.xml" --results-directory test-resultsTest adapter not loaded
If tests are not discovered or you see No test is available, ensure the NUnit3TestAdapter package is
referenced in your .csproj:
dotnet add package NUnit3TestAdapterAlso verify that Microsoft.NET.Test.Sdk is installed — this is required for the dotnet test command
to discover and run NUnit tests:
dotnet add package Microsoft.NET.Test.SdkWrong XML format (NUnit 2 vs NUnit 3)
The TestKase reporter expects NUnit 3 XML format. If you are using an older NUnit 2 runner or a third-party logger that produces NUnit 2 format, the reporter will fail to parse the results.
To verify you are using NUnit 3 format, check the root element of the generated XML:
- NUnit 3:
<test-run>root element - NUnit 2:
<test-results>root element
If you see <test-results>, switch to the NunitXml.TestLogger package which produces the correct
NUnit 3 format. Do not use the older NUnit.ConsoleRunner unless you confirm it outputs NUnit 3 XML.