tunit-usage
Development patterns and setup instructions for TUnit 1.45.x in .NET 10 environments.
Install
mkdir -p .claude/skills/tunit-usage && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/15970" && unzip -o skill.zip -d .claude/skills/tunit-usage && rm skill.zipInstalls to .claude/skills/tunit-usage
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
TUnit 1.45.x test framework patterns for .NET 10. Use when setting up a TUnit test project, writing tests, skipping tests conditionally, wiring session-level fixtures, or troubleshooting TUnit API issues. Covers: project setup, skip mechanism, Before/After hooks, Assert syntax, ClassDataSource shariKey capabilities
- →Set up a TUnit test project for .NET 10
- →Write asynchronous tests using `async Task` and `[Test]` attribute
- →Use TUnit Assert syntax for various checks
- →Implement conditional test skipping using `SkipTestException`
- →Wire session-level fixtures with `[Before(TestSession)]` and `[After(TestSession)]`
- →Share fixtures across classes using `ClassDataSource`
How it works
This skill provides usage patterns for the TUnit 1.45.x test framework, covering project setup, test writing, assertion syntax, conditional skipping, and session-level fixtures.
Inputs & outputs
When to use tunit-usage
- →Set up TUnit project
- →Write async tests
- →Implement session fixtures
- →Configure test runner
About this skill
TUnit 1.45.x Usage Patterns
Project Setup
global.json — required to enable Microsoft.Testing.Platform runner
{
"sdk": { "version": "10.0.100", "rollForward": "latestMinor" },
"test": { "runner": "Microsoft.Testing.Platform" }
}
Test project .csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType> <!-- Required for TUnit -->
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<EnforceCodeStyleInBuild>false</EnforceCodeStyleInBuild>
<NoWarn>$(NoWarn);CS1591</NoWarn> <!-- XML docs not required in tests -->
</PropertyGroup>
<ItemGroup>
<PackageReference Include="TUnit" /> <!-- Version from Directory.Packages.props -->
</ItemGroup>
</Project>
Directory.Packages.props entry
<PackageVersion Include="TUnit" Version="1.45.22" />
Writing Tests
using TUnit.Core;
public sealed class MyTests
{
[Test]
public async Task Something_GivenCondition_ReturnsExpected()
{
var result = 2 + 2;
await Assert.That(result).IsEqualTo(4);
}
}
- No base class required
- Methods must be
async Taskand decorated with[Test] - One
await Assert.That(...)per logical assertion
Assert Syntax
await Assert.That(value).IsEqualTo(expected);
await Assert.That(value).IsNotEqualTo(unexpected);
await Assert.That(value).IsTrue();
await Assert.That(value).IsFalse();
await Assert.That(value).IsNull();
await Assert.That(value).IsNotNull();
await Assert.That(value).IsGreaterThan(n);
await Assert.That(value).IsTypeOf<SomeType>();
await Assert.That(collection).HasCount().EqualTo(n); // NOT .HasCount(n)
await Assert.That(str).Contains("substring");
// Exceptions
await Assert.That(() => DoSomething()).Throws<ArgumentNullException>();
await Assert.That(() => DoSomething()).Throws<MyException>()
.WithMessageContaining("expected fragment");
Skipping Tests
The skip exception namespace — COMMON PITFALL
// WRONG — CS0246, type not in TUnit.Core directly
using TUnit.Core;
throw new SkipTestException("reason");
// CORRECT — it lives in TUnit.Core.Exceptions
using TUnit.Core.Exceptions;
throw new SkipTestException("reason");
Conditional skip inside a test
[Test]
public async Task MyTest()
{
if (!someCondition)
{
throw new SkipTestException("Condition not met on this machine.");
}
// ... rest of test
}
Reusable skip helper
using TUnit.Core.Exceptions;
internal static class TestEnvironment
{
internal static Task SkipIfUnavailableAsync()
{
if (!IsAvailable)
{
throw new SkipTestException("Resource not available.");
}
return Task.CompletedTask;
}
}
Session-Level Fixtures (run once per test run)
Use a static class with [Before(TestSession)] / [After(TestSession)].
No base class, no interface needed.
using TUnit.Core;
internal static class GlobalHooks
{
[Before(TestSession)]
public static async Task InitializeAsync()
{
// Runs once before any test in the session
await Task.Run(() => MyRuntime.Initialize());
}
[After(TestSession)]
public static async Task ShutdownAsync()
{
// Runs once after all tests complete
if (MyRuntime.IsInitialized)
{
await Task.Run(() => MyRuntime.Shutdown());
}
}
}
Other hook granularities
| Attribute | Runs |
|---|---|
[Before(TestSession)] | Once before entire test run |
[After(TestSession)] | Once after entire test run |
[Before(Class)] | Before each test class |
[After(Class)] | After each test class |
[Before(Test)] | Before each individual test |
[After(Test)] | After each individual test |
Integration Test Base Class Pattern
internal abstract class IntegrationTestBase
{
[Before(Test)]
public async Task RequireResourceAsync()
{
await TestEnvironment.SkipIfUnavailableAsync();
}
}
public sealed class MyIntegrationTests : IntegrationTestBase
{
[Test]
public async Task Does_Something_WithRealResource()
{
// Auto-skips via base class [Before(Test)] if resource unavailable
}
}
ClassDataSource — Shared Fixtures
// SharedType enum values in TUnit 1.45:
// None, PerClass, PerAssembly, PerTestSession
// NOTE: SharedType.Globally does NOT exist — use PerTestSession instead
[ClassDataSource<MyFixture>(Shared = SharedType.PerTestSession)]
public class MyTests
{
// TUnit injects MyFixture as constructor parameter or property
}
To make the fixture initialize async, implement IAsyncInitializer from TUnit.Core
and IAsyncDisposable:
using TUnit.Core;
internal sealed class MyFixture : IAsyncInitializer, IAsyncDisposable
{
public async Task InitializeAsync()
{
await SetUpAsync();
}
public async ValueTask DisposeAsync()
{
await TearDownAsync();
}
}
Common Pitfalls
| Problem | Cause | Fix |
|---|---|---|
SkipTestException not found | Wrong namespace | using TUnit.Core.Exceptions; |
SharedType.Globally not found | Doesn't exist | Use SharedType.PerTestSession |
IAsyncInitializer not found | Missing using | using TUnit.Core; |
| Test project won't run | Missing <OutputType>Exe</OutputType> | Add to csproj |
| Tests not discovered | Missing global.json runner | Add "test": { "runner": "Microsoft.Testing.Platform" } |
.HasCount(n) compile error | API changed | Use .HasCount().EqualTo(n) |
Constant bool assertion error | TUnit analyzer | Use IsTypeOf<bool>() or just remove trivial assertions |
When not to use it
- →When using a TUnit version other than 1.45.x
- →When developing for a .NET version other than 10
- →When not using the Microsoft.Testing.Platform runner
Prerequisites
Limitations
- →Specific to TUnit 1.45.x
- →Specific to .NET 10
- →Requires `Microsoft.Testing.Platform` runner
How it compares
This skill offers specific TUnit 1.45.x patterns for .NET 10, providing detailed guidance for test project configuration and test writing that differs from general .NET testing frameworks.
Compared to similar skills
tunit-usage side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| tunit-usage (this skill) | 0 | 2mo | No flags | Intermediate |
| csharp-pro | 9 | 4mo | No flags | Intermediate |
| performance-benchmark | 3 | 5mo | No flags | Intermediate |
| run-device-tests | 3 | 2mo | Review | Advanced |
Try saying
Example prompts that trigger this skill in your AI assistant.
You might also like
csharp-pro
sickn33
Write modern C# code with advanced features like records, pattern matching, and async/await. Optimizes .NET applications, implements enterprise patterns, and ensures comprehensive testing. Use PROACTIVELY for C# refactoring, performance optimization, or complex .NET solutions.
performance-benchmark
dotnet
Generate and run ad hoc performance benchmarks to validate code changes. Use this when asked to benchmark, profile, or validate the performance impact of a code change in dotnet/runtime.
run-device-tests
dotnet
Build and run .NET MAUI device tests locally with category filtering. Supports iOS, MacCatalyst, Android on macOS; Android, Windows on Windows. Use TestFilter to run specific test categories.
backend-testing
exceptionless
Backend testing with xUnit, Foundatio.Xunit, integration tests with AppWebHostFactory, FluentClient, ProxyTimeProvider for time manipulation, and test data builders. Keywords: xUnit, Fact, Theory, integration tests, AppWebHostFactory, FluentClient, ProxyTimeProvider, TimeProvider, Foundatio.Xunit, TestWithLoggingBase, test data builders
bunit-test-migration
FritzAndFriends
Migrate bUnit test files from deprecated beta API (1.0.0-beta-10) to bUnit 2.x stable API. Use this when working on .razor test files in BlazorWebFormsComponents.Test that contain old patterns like TestComponentBase, Fixture, or SnapshotTest.
deployment-e2e-testing
dotnet
Guide for writing Aspire deployment end-to-end tests. Use this when asked to create, modify, or debug deployment E2E tests that deploy to Azure.