/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],
$ npx -y skills add managedcode/dotnet-skills --skill nunit --agent claude-codeHow 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.mdname: 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(liRead more
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(liStop 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.
Repo: managedcode/dotnet-skills
Other skills on dotnet-skills.
- /aspnet-core
Build, debug, modernize, or review ASP.NET Core applications with correct hosting, middleware, security, configuration, logging, and deployment patterns on current .NET. USE FOR: working on ASP.NET Core apps, services, or middleware; changing auth, routing, configuration,
Open skill - /aspire
Build, upgrade, and operate Aspire 13.4.x C# or TypeScript application hosts with the current CLI, AppHost, ServiceDefaults, integrations, dashboard, testing, MCP, and deployment patterns for distributed apps. USE FOR: Aspire.AppHost.Sdk, Aspire.Hosting.*,
Open skill - /azure-functions
Build, review, or migrate Azure Functions in .NET with correct execution model, isolated worker setup, bindings, DI, and Durable Functions patterns. USE FOR: working on Azure Functions in .NET; migrating from the in-process model to the isolated worker model; adding Durable
Open skill - /blazor
Build and review Blazor applications across server, WebAssembly, web app, and hybrid scenarios with correct component design, state flow, rendering, and hosting choices. USE FOR: building interactive web UIs with C# instead of JavaScript; choosing between Server, WebAssembly, or
Open skill - /entity-framework6
Maintain or migrate EF6-based applications with realistic guidance on what to keep, what to modernize, and when EF Core is or is not the right next step. USE FOR: EF6 codebases; runtime versus ORM migration decisions; EDMX, code-first, ObjectContext, and legacy data-access
Open skill - /entity-framework-core
Design, tune, or review EF Core data access with proper modeling, migrations, query translation, performance, and lifetime management for modern .NET applications. USE FOR: DbContext, migrations, model configuration, EF queries, tracking, loading, performance, transactions, and
Open skill

