
Csharp Tunit
Guide an agent to write focused TUnit tests in a separate `[ProjectName].Tests` project on .NET 8+ with AAA structure and fluent `await Assert.That()` assertions.
Overview
csharp-tunit is an agent skill for the Ship phase that teaches TUnit unit-testing structure, lifecycle hooks, and data-driven patterns for .NET 8+ projects.
Install
npx skills add https://github.com/github/awesome-copilot --skill csharp-tunitWhat is this skill?
- Separate test project naming and TUnit + TUnit.Assertions package setup for .NET 8+
- `[Test]` methods with `MethodName_Scenario_ExpectedBehavior` naming and AAA layout
- Lifecycle hooks from `[Before(Test)]` through `[Before(TestSession)]` and matching `[After(...)]` hooks
- Fluent async assertions via `await Assert.That()` instead of xUnit `[Fact]` patterns
- Data-driven testing approaches alongside standard single-behavior tests
Adoption & trust: 8.5k installs on skills.sh; 34.6k GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
Your agent writes xUnit-style tests or scattered assertions when your repo standard is TUnit on .NET 8 or higher.
Who is it for?
Solo builders shipping C# libraries or APIs who standardized on TUnit and want agents to stop mixing xUnit idioms.
Skip if: Teams still on xUnit or NUnit with no migration plan, or pure integration/E2E suites where TUnit conventions are irrelevant.
When should I use this skill?
When you need best practices for TUnit unit testing, including data-driven tests.
What do I get? / Deliverables
You get consistent test projects, correctly attributed TUnit tests, and fluent assertions that run cleanly under `dotnet test`.
- TUnit test classes and methods following AAA and naming conventions
- Configured lifecycle hooks for test, class, or assembly scope
- Data-driven test cases with appropriate assertions
Recommended Skills
Journey fit
Unit-test authoring and project conventions belong in Ship when you are validating behavior before release, not during initial product design. Testing subphase is the canonical shelf for xUnit-style replacement guidance, lifecycle hooks, and data-driven TUnit patterns.
How it compares
Use as a TUnit-specific test-style guide instead of generic “write unit tests” chat without framework rules.
Common Questions / FAQ
Who is csharp-tunit for?
Solo and indie .NET developers who want their coding agent to produce TUnit tests that match project layout and .NET 8+ requirements.
When should I use csharp-tunit?
During Ship when adding or refactoring unit tests—especially when scaffolding a new `[ProjectName].Tests` project, naming tests, or setting up data-driven cases before a release.
Is csharp-tunit safe to install?
It is procedural documentation only; review the Security Audits panel on this Prism page before trusting any third-party skill source.
SKILL.md
READMESKILL.md - Csharp Tunit
# TUnit Best Practices Your goal is to help me write effective unit tests with TUnit, covering both standard and data-driven testing approaches. ## Project Setup - Use a separate test project with naming convention `[ProjectName].Tests` - Reference TUnit package and TUnit.Assertions for fluent assertions - Create test classes that match the classes being tested (e.g., `CalculatorTests` for `Calculator`) - Use .NET SDK test commands: `dotnet test` for running tests - TUnit requires .NET 8.0 or higher ## Test Structure - No test class attributes required (like xUnit/NUnit) - Use `[Test]` attribute for test methods (not `[Fact]` like xUnit) - Follow the Arrange-Act-Assert (AAA) pattern - Name tests using the pattern `MethodName_Scenario_ExpectedBehavior` - Use lifecycle hooks: `[Before(Test)]` for setup and `[After(Test)]` for teardown - Use `[Before(Class)]` and `[After(Class)]` for shared context between tests in a class - Use `[Before(Assembly)]` and `[After(Assembly)]` for shared context across test classes - TUnit supports advanced lifecycle hooks like `[Before(TestSession)]` and `[After(TestSession)]` ## Standard Tests - Keep tests focused on a single behavior - Avoid testing multiple behaviors in one test method - Use TUnit's fluent assertion syntax with `await Assert.That()` - Include only the assertions needed to verify the test case - Make tests independent and idempotent (can run in any order) - Avoid test interdependencies (use `[DependsOn]` attribute if needed) ## Data-Driven Tests - Use `[Arguments]` attribute for inline test data (equivalent to xUnit's `[InlineData]`) - Use `[MethodData]` for method-based test data (equivalent to xUnit's `[MemberData]`) - Use `[ClassData]` for class-based test data - Create custom data sources by implementing `ITestDataSource` - Use meaningful parameter names in data-driven tests - Multiple `[Arguments]` attributes can be applied to the same test method ## Assertions - Use `await Assert.That(value).IsEqualTo(expected)` for value equality - Use `await Assert.That(value).IsSameReferenceAs(expected)` for reference equality - Use `await Assert.That(value).IsTrue()` or `await Assert.That(value).IsFalse()` for boolean conditions - Use `await Assert.That(collection).Contains(item)` or `await Assert.That(collection).DoesNotContain(item)` for collections - Use `await Assert.That(value).Matches(pattern)` for regex pattern matching - Use `await Assert.That(action).Throws<TException>()` or `await Assert.That(asyncAction).ThrowsAsync<TException>()` to test exceptions - Chain assertions with `.And` operator: `await Assert.That(value).IsNotNull().And.IsEqualTo(expected)` - Use `.Or` operator for alternative conditions: `await Assert.That(value).IsEqualTo(1).Or.IsEqualTo(2)` - Use `.Within(tolerance)` for DateTime and numeric comparisons with tolerance - All assertions are asynchronous and must be awaited ## Advanced Features - Use `[Repeat(n)]` to repeat tests multiple times - Use `[Retry(n)]` for automatic retry on failure - Use `[ParallelLimit<T>]` to control parallel execution limits - Use `[Skip("reason")]` to skip tests conditionally - Use `[DependsOn(nameof(OtherTest))]` to create test dependencies - Use `[Timeout(milliseconds)]` to set test timeouts - Create custom attributes by extending TUnit's base attributes ## Test Organization - Group tests by feature or component - Use `[Category("CategoryName")]` for test categorization - Use `[DisplayName("Custom Test Name")]` for custom test names - Consider using `TestContext` for test diagnostics and information - Use conditional attributes like custom `[WindowsOnly]` for platform-specific tests ## Performance and Parallel Execution - TUnit runs tests in parallel by default (unlike xUnit which requires explicit configuration) - Use `[NotInParallel]` to disable parallel execution for specific tests - Use `[ParallelLi