csharp-tunit
Skill2 starsChanged 27 days agoMITView on GitHub
Get best practices for TUnit unit testing, including data-driven tests
2 other projects use a version of this.
Adopted by
Most recently taken up by
- github/awesome-copilotword for word, first seen Oct 25, 2026
- glennawatson/CSharpAgentSkillstheir own version, first seen Oct 1, 2026
Other versions2 projects use a version of this.
Word for word · 1
- github/awesome-copilot★ 41k100% same
Edited · 0
None found.
Wrote their own version · 1
- glennawatson/CSharpAgentSkills★ 2same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository192 other files it gives its agents.
- clickhouse-architecture-advisor/AGENTS.mdAGENTS.md
- clickhouse-best-practices/AGENTS.mdAGENTS.md
- unsafe-checker/AGENTS.mdAGENTS.md
- alertmanager-querySkill
- analyzing-range-distributionSkill
- analyzing-schema-change-storage-riskSkill
- argocdSkill
- aspire-configurationSkill
- aspire-integration-testingSkill
- aspire-service-defaultsSkill
- auditing-cloud-cluster-securitySkill
- auditing-table-statisticsSkill
- benchmarking-transaction-patternsSkill
- cepthSkill
- chdb-datastoreSkill
- chdb-sqlSkill
- clickhouse-architecture-advisorSkill
- clickhouse-best-practicesSkill
- clickhousectl-cloud-deploySkill
- clickhousectl-local-devSkill
- cockroachdb-sqlSkill
- coding-guidelinesSkill
- configuring-audit-loggingSkill
- configuring-ip-allowlistsSkill
- configuring-log-exportSkill
- configuring-private-connectivitySkill
- configuring-sso-and-scimSkill
- create-technical-architecture-documentSkill
- csharp-mstestSkill
- csharp-xunitSkill
- designing-application-transactionsSkill
- designing-multi-region-applicationsSkill
- domain-cliSkill
- domain-cloud-nativeSkill
- domain-embeddedSkill
- domain-fintechSkill
- domain-iotSkill
- domain-mlSkill
- domain-webSkill
- dotnet-aot-wasmSkill
- dotnet-aspire-patternsSkill
- dotnet-benchmarkdotnetSkill
- dotnet-blazor-authSkill
- dotnet-blazor-componentsSkill
- dotnet-blazor-patternsSkill
- dotnet-blazor-testingSkill
- dotnet-channelsSkill
- dotnet-ci-benchmarkingSkill
- dotnet-cli-architectureSkill
- dotnet-cli-distributionSkill
- dotnet-cli-packagingSkill
- dotnet-cli-release-pipelineSkill
- dotnet-containersSkill
- dotnet-cryptographySkill
- dotnet-csharp-dependency-injectionSkill
- dotnet-csharp-modern-patternsSkill
- dotnet-csharp-nullable-reference-typesSkill
- dotnet-csharp-source-generatorsSkill
- dotnet-maui-doctorSkill
- dotnet-maui-doctorSkill
- The first 60 shown.
The file
Show its rules and text
We split this skill into the rules it gives an agent
41 rules. About 0 are common, 7 are distinctive, and 34 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈7
Distinctive · estimate
This author's own choices. Worth a look.
34
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 12
Use a separate test project with naming convention [ProjectName].Tests
- Very specific: line 14
Create test classes that match the classes being tested (e.g., CalculatorTests for Calculator)
- Very specific: line 15
Use .NET SDK test commands: dotnet test for running tests
- Distinctive: line 20
No test class attributes required (like xUnit/NUnit)
- Very specific: line 21
Use [Test] attribute for test methods (not [Fact] like xUnit)
- Distinctive: line 22
Follow the Arrange-Act-Assert (AAA) pattern
- Very specific: line 24
Use lifecycle hooks: [Before(Test)] for setup and [After(Test)] for teardown
- Very specific: line 25
Use [Before(Class)] and [After(Class)] for shared context between tests in a class
- Very specific: line 26
Use [Before(Assembly)] and [After(Assembly)] for shared context across test classes
- Distinctive: line 31
Keep tests focused on a single behavior
- Distinctive: line 32
Avoid testing multiple behaviors in one test method
- Very specific: line 33
Use TUnit's fluent assertion syntax with await Assert.That()
- Very specific: line 36
Avoid test interdependencies (use [DependsOn] attribute if needed)
- Very specific: line 40
Use [Arguments] attribute for inline test data (equivalent to xUnit's [InlineData])
- Very specific: line 41
Use [MethodData] for method-based test data (equivalent to xUnit's [MemberData])
- Very specific: line 42
Use [ClassData] for class-based test data
- Very specific: line 43
Create custom data sources by implementing ITestDataSource
- Distinctive: line 44
Use meaningful parameter names in data-driven tests
- Very specific: line 49
Use await Assert.That(value).IsEqualTo(expected) for value equality
- Very specific: line 50
Use await Assert.That(value).IsSameReferenceAs(expected) for reference equality
- Very specific: line 51
Use await Assert.That(value).IsTrue() or await Assert.That(value).IsFalse() for boolean conditions
- Very specific: line 52
Use await Assert.That(collection).Contains(item) or await Assert.That(collection).DoesNotContain(item) for collections
- Very specific: line 53
Use await Assert.That(value).Matches(pattern) for regex pattern matching
- Very specific: line 54
Use await Assert.That(action).Throws<TException>() or await Assert.That(asyncAction).ThrowsAsync<TException>() to test exceptions
- Very specific: line 56
Use .Or operator for alternative conditions: await Assert.That(value).IsEqualTo(1).Or.IsEqualTo(2)
- Very specific: line 57
Use .Within(tolerance) for DateTime and numeric comparisons with tolerance
- Distinctive: line 58
All assertions are asynchronous and must be awaited
- Very specific: line 62
Use [Repeat(n)] to repeat tests multiple times
- Very specific: line 63
Use [Retry(n)] for automatic retry on failure
- Very specific: line 64
Use [ParallelLimit<T>] to control parallel execution limits
- Very specific: line 65
Use [Skip("reason")] to skip tests conditionally
- Very specific: line 66
Use [DependsOn(nameof(OtherTest))] to create test dependencies
- Very specific: line 67
Use [Timeout(milliseconds)] to set test timeouts
- Distinctive: line 68
Create custom attributes by extending TUnit's base attributes
- Very specific: line 73
Use [Category("CategoryName")] for test categorization
- Very specific: line 74
Use [DisplayName("Custom Test Name")] for custom test names
- Very specific: line 75
Consider using TestContext for test diagnostics and information
- Very specific: line 76
Use conditional attributes like custom [WindowsOnly] for platform-specific tests
- Very specific: line 81
Use [NotInParallel] to disable parallel execution for specific tests
- Very specific: line 82
Use [ParallelLimit<T>] with custom limit classes to control concurrency
- Very specific: line 84
Use [Repeat(n)] with [ParallelLimit<T>] for load testing scenarios
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
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.,
CalculatorTestsforCalculator) - Use .NET SDK test commands:
dotnet testfor 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()orawait Assert.That(value).IsFalse()for boolean conditions - Use
await Assert.That(collection).Contains(item)orawait 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>()orawait Assert.That(asyncAction).ThrowsAsync<TException>()to test exceptions - Chain assertions with
.Andoperator:await Assert.That(value).IsNotNull().And.IsEqualTo(expected) - Use
.Oroperator 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
TestContextfor 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
[ParallelLimit<T>]with custom limit classes to control concurrency - Tests within the same class run sequentially by default
- Use
[Repeat(n)]with[ParallelLimit<T>]for load testing scenarios
Migration from xUnit
- Replace
[Fact]with[Test] - Replace
[Theory]with[Test]and use[Arguments]for data - Replace
[InlineData]with[Arguments] - Replace
[MemberData]with[MethodData] - Replace
Assert.Equalwithawait Assert.That(actual).IsEqualTo(expected) - Replace
Assert.Truewithawait Assert.That(condition).IsTrue() - Replace
Assert.Throws<T>withawait Assert.That(action).Throws<T>() - Replace constructor/IDisposable with
[Before(Test)]/[After(Test)] - Replace
IClassFixture<T>with[Before(Class)]/[After(Class)]
Why TUnit over xUnit?
TUnit offers a modern, fast, and flexible testing experience with advanced features not present in xUnit, such as asynchronous assertions, more refined lifecycle hooks, and improved data-driven testing capabilities. TUnit's fluent assertions provide clearer and more expressive test validation, making it especially suitable for complex .NET projects.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

