Skip to content
Development
Skill

/nunit

Write, run, or repair .NET tests that use NUnit. Use when a repo uses `NUnit`, `[Test]`, `[TestCase]`, `[TestFixture]`, or NUnit3TestAdapter for VSTest or Microsoft.Testing.Platform execution. USE FOR: writing or reviewing NUnit tests; using [Test], [TestCase], [TestFixture],

From plugin
dotnet-skills
466200 skills50 agents
Install
$ npx -y skills add managedcode/dotnet-skills --skill nunit --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/nunit

Context preview

The summary Claude sees to decide when to auto-load this skill.

Write, run, or repair .NET tests that use NUnit. Use when a repo uses `NUnit`, `[Test]`, `[TestCase]`, `[TestFixture]`, or NUnit3TestAdapter for VSTest or Microsoft.Testing.Platform execution. USE FOR: writing or reviewing NUnit tests; using [Test], [TestCase], [TestFixture],

SKILL.md

nunit.SKILL.md
name: nunit
description: "Write, run, or repair .NET tests that use NUnit. Use when a repo uses `NUnit`, `[Test]`, `[TestCase]`, `[TestFixture]`, or NUnit3TestAdapter for VSTest or Microsoft.Testing.Platform execution. USE FOR: writing or reviewing NUnit tests; using [Test], [TestCase], [TestFixture], [SetUp], [TearDown] attributes; configuring NUnit3TestAdapter or NUnit.Analyzers. DO NOT USE FOR: unrelated stacks; generic tasks that do not need this specific guidance. INVOKES: inspect the repository context, edit targeted files, and run relevant build, test, lint, or validation commands when changes are made."
compatibility: "Requires NUnit 3.x or 4.x packages and appropriate test adapter."

NUnit Testing

Trigger On

  • writing or reviewing NUnit tests
  • using `[Test]`, `[TestCase]`, `[TestFixture]`, `[SetUp]`, `[TearDown]` attributes
  • configuring NUnit3TestAdapter or NUnit.Analyzers
  • migrating between NUnit versions
  • integrating NUnit with CI pipelines

Documentation

  • [NUnit Documentation](https://docs.nunit.org/)
  • [NUnit GitHub](https://github.com/nunit/nunit)
  • [NUnit3TestAdapter](https://github.com/nunit/nunit3-vs-adapter)
  • [NUnit Analyzers](https://github.com/nunit/nunit.analyzers)

Workflow

1. Detect whether the project uses NUnit 3.x or 4.x and which runner path is active: VSTest, Microsoft.Testing.Platform, IDE runner, or CI wrapper. 2. Keep test fixtures small, prefer focused assertions with `Assert.That`, and use `TestCase` or `TestCaseSource` only when parameterization improves signal. 3. Add `NUnit3TestAdapter`, `Microsoft.NET.Test.Sdk`, and `NUnit.Analyzers` when CLI discovery or analyzer coverage is missing. 4. Validate with the repo's real test command before changing assertion style or lifecycle hooks.

References

  • [patterns.md](references/patterns.md) — Test patterns, assertions, parameterized tests, lifecycle
  • [anti-patterns.md](references/anti-patterns.md) — Common NUnit mistakes and fixes

Package Selection

| Package | Purpose | |---------|---------| | `NUnit` | Core testing framework | | `NUnit3TestAdapter` | VSTest adapter for `dotnet test` | | `NUnit.Analyzers` | Roslyn analyzers for NUnit best practices | | `Microsoft.NET.Test.Sdk` | Required for test discovery |

Project Setup

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <IsPackable>false</IsPackable>
    <IsTestProject>true</IsTestProject>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.*" />
    <PackageReference Include="NUnit" Version="4.*" />
    <PackageReference Include="NUnit3TestAdapter" Version="4.*" />
    <PackageReference Include="NUnit.Analyzers" Version="4.*">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
    </PackageReference>
  </ItemGroup>
</Project>

Test Patterns

Basic Test Structure

[TestFixture]
public class CalculatorTests
{
    private Calculator _calculator;

    [SetUp]
    public void SetUp()
    {
        _calculator = new Calculator();
    }

    [TearDown]
    public void TearDown()
    {
        _calculator?.Dispose();
    }

    [Test]
    public void Add_TwoPositiveNumbers_ReturnsSum()
    {
        var result = _calculator.Add(2, 3);

        Assert.That(result, Is.EqualTo(5));
    }

    [Test]
    public void Divide_ByZero_ThrowsException()
    {
        Assert.Throws<DivideByZeroException>(() => _calculator.Divide(10, 0));
    }
}

Parameterized Tests with TestCase

[TestFixture]
public class ValidationTests
{
    [TestCase("", false)]
    [TestCase("a", false)]
    [TestCase("ab", false)]
    [TestCase("abc", true)]
    [TestCase("valid@email.com", true)]
    public void IsValid_VariousInputs_ReturnsExpected(string input, bool expected)
    {
        var result = Validator.IsValid(input);

        Assert.That(result, Is.EqualTo(expected));
    }

    [TestCase(1, 2, ExpectedResult = 3)]
    [TestCase(-1, 1, ExpectedResult = 0)]
    [TestCase(100, 200, ExpectedResult = 300)]
    public int Add_TestCases_ReturnsExpectedResult(int a, int b)
    {
        return _calculator.Add(a, b);
    }
}

TestCaseSource for Complex Data

[TestFixture]
public class OrderTests
{
    private static IEnumerable<TestCaseData> OrderTestCases()
    {
        yield return new TestCaseData(
            new Order { Items = new[] { new Item { Price = 10 }, new Item { Price = 20 } } },
            30m
        ).SetName("TwoItems_CalculatesTotal");

        yield return new TestCaseData(
            new Order { Items = Array.Empty<Item>() },
            0m
        ).SetName("EmptyOrder_ReturnsZero");

        yield return new TestCaseData(
            new Order { Items = new[] { new Item { Price = 100 } }, DiscountPercent = 10 },
            90m
        ).SetName("WithDiscount_AppliesDiscount");
    }

    [TestCaseSource(nameof(OrderTestCases))]
    public void CalculateTotal_VariousOrders_ReturnsExpected(Order order, decimal expected)
    {
        var result = order.CalculateTotal();

        Assert.That(result, Is.EqualTo(expected));
    }
}

Constraint-Based Assertions

[Test]
public void AssertionExamples()
{
    // Equality
    Assert.That(actual, Is.EqualTo(expected));
    Assert.That(actual, Is.Not.EqualTo(other));

    // Comparison
    Assert.That(value, Is.GreaterThan(5));
    Assert.That(value, Is.LessThanOrEqualTo(10));
    Assert.That(value, Is.InRange(1, 100));

    // String
    Assert.That(str, Does.StartWith("Hello"));
    Assert.That(str, Does.Contain("world"));
    Assert.That(str, Does.Match(@"\d{3}-\d{4}"));
    Assert.That(str, Is.EqualTo("HELLO").IgnoreCase);

    // Collection
    Assert.That(list, Has.Count.EqualTo(5));
    Assert.That(list, Contains.Item("expected"));
    Assert.That(list, Is.All.GreaterThan(0));
    Assert.That(list, Is.Unique);
    Assert.That(li
Read more
Ships withdotnet-skills

Stop explaining .NET to your AI. Start building. We've all been there: asking Claude to use Entity Framework, only to get EF6 patterns in a .NET 8 project. Explaining to Copilot that Blazor Server and Blazor WebAssembly aren't the same thing.

Get the whole plugin

Other skills on dotnet-skills.