From qa-unit-tests-net
Configures and runs xUnit.net (xUnit v2 + v3) - current de facto .NET test framework with `[Fact]` for single tests + `[Theory]` + `[InlineData]`/`[ClassData]`/`[MemberData]` for parametrized; collection fixtures (`[Collection]`) + class fixtures (`IClassFixture<T>`) for shared setup; output via `ITestOutputHelper`; parallel test config via assembly attribute. Use when working with .NET (C# / F# / VB.NET) on the modern test stack.
How this skill is triggered — by the user, by Claude, or both
Slash command
/qa-unit-tests-net:xunit-testsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Per [xunit.net/docs][xn-docs]:
Per xunit.net/docs:
xUnit.net is the current .NET test standard (used by .NET Foundation projects + Microsoft's own .NET runtime). v3 released 2024; v2 still widely used in production.
dotnet new xunit -n MyProjectTests
# Or in existing project:
dotnet add package xunit
dotnet add package xunit.runner.visualstudio
dotnet add package Microsoft.NET.Test.Sdk
using Xunit;
public class CalculatorTests
{
[Fact]
public void Adds_TwoNumbers()
{
Assert.Equal(3, Calculator.Add(1, 2));
}
}
Run: dotnet test.
Per xn-docs:
[Theory]
[InlineData(1, 2, 3)]
[InlineData(0, 0, 0)]
[InlineData(-1, 1, 0)]
public void Adds_VariousInputs(int a, int b, int expected)
{
Assert.Equal(expected, Calculator.Add(a, b));
}
// Class-based data source
public class AddTestData : IEnumerable<object[]>
{
public IEnumerator<object[]> GetEnumerator()
{
yield return new object[] { 1, 2, 3 };
yield return new object[] { 0, 0, 0 };
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
[Theory]
[ClassData(typeof(AddTestData))]
public void Adds_FromClassData(int a, int b, int expected) { ... }
// Method-based
public static IEnumerable<object[]> AddCases =>
new List<object[]> {
new object[] { 1, 2, 3 },
new object[] { 0, 0, 0 },
};
[Theory]
[MemberData(nameof(AddCases))]
public void Adds_FromMemberData(int a, int b, int expected) { ... }
[Fact(Skip = "Requires staging DB")]
public void SkippedTest() { }
[Fact]
[Trait("Category", "Integration")]
public void IntegrationTest() { }
// Filter: dotnet test --filter "Category=Integration"
// Per-test (default): xUnit creates a new test class instance per test
public class CalculatorTests {
private readonly Calculator _calc;
public CalculatorTests() { _calc = new Calculator(); }
// ...
}
// Class fixture: shared across all tests in a class
public class DatabaseFixture : IDisposable {
public DbConnection Connection { get; }
public DatabaseFixture() { Connection = OpenConnection(); }
public void Dispose() { Connection.Close(); }
}
public class UserTests : IClassFixture<DatabaseFixture> {
private readonly DatabaseFixture _fixture;
public UserTests(DatabaseFixture fixture) { _fixture = fixture; }
[Fact] public void TestsUser() { /* uses _fixture.Connection */ }
}
// Collection fixture: shared across multiple test classes
[CollectionDefinition("DbCollection")]
public class DbCollection : ICollectionFixture<DatabaseFixture> { }
[Collection("DbCollection")]
public class TestsA { ... }
[Collection("DbCollection")]
public class TestsB { ... } // shares the same DatabaseFixture
xUnit suppresses Console.WriteLine in tests. Use ITestOutputHelper:
public class TestsWithOutput {
private readonly ITestOutputHelper _output;
public TestsWithOutput(ITestOutputHelper output) { _output = output; }
[Fact]
public void LogsContext() {
_output.WriteLine("Test running at {0}", DateTime.UtcNow);
}
}
By default xUnit runs collections in parallel; tests in the same collection run sequentially.
// Disable parallelism for an assembly:
[assembly: CollectionBehavior(DisableTestParallelization = true)]
// Or per-collection:
[assembly: CollectionBehavior(MaxParallelThreads = 4)]
result.Should().Be(42);
list.Should().HaveCount(3).And.Contain("alice");
result.Should().BeOfType<Success>().Which.Value.Should().Be(42);
See fluentassertions. Note:
FluentAssertions changed license in 2024 (paid commercial; free for
OSS); v6 is the last fully-free version.
- run: dotnet test --logger "trx;LogFileName=test-results.trx" \
--collect:"XPlat Code Coverage" -- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=opencover
- uses: codecov/codecov-action@v4
with: { files: ./coverage/coverage.opencover.xml }
| Anti-pattern | Why it fails | Fix |
|---|---|---|
Console.WriteLine instead of ITestOutputHelper | Output suppressed | Use ITestOutputHelper (Step 6) |
Use [Theory] without data attribute | Test never runs | Always include [InlineData] etc. |
Shared mutable state in IClassFixture | Test order dependence | Per-test fresh state OR [Collection] synchronization |
| Skip parallel tuning at scale | Slow CI | Per-assembly + per-collection config (Step 7) |
--filter.nunit-tests,
mstest-tests,
fluentassertions - sister toolstest-code-conventionsnpx claudepluginhub testland/qa --plugin qa-unit-tests-netProvides CDSS development patterns for drug interaction checking, dose validation, clinical scoring (NEWS2, qSOFA), and alert classification integrated into EMR workflows.