agentleFS
TeddyAlbinaTeddyAlbina/skills/csharp-tunit/SKILL.md

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

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
  1. Very specific:

    Use a separate test project with naming convention [ProjectName].Tests

    line 12
  2. Very specific:

    Create test classes that match the classes being tested (e.g., CalculatorTests for Calculator)

    line 14
  3. Very specific:

    Use .NET SDK test commands: dotnet test for running tests

    line 15
  4. Distinctive:

    No test class attributes required (like xUnit/NUnit)

    line 20
  5. Very specific:

    Use [Test] attribute for test methods (not [Fact] like xUnit)

    line 21
  6. Distinctive:

    Follow the Arrange-Act-Assert (AAA) pattern

    line 22
  7. Very specific:

    Use lifecycle hooks: [Before(Test)] for setup and [After(Test)] for teardown

    line 24
  8. Very specific:

    Use [Before(Class)] and [After(Class)] for shared context between tests in a class

    line 25
  9. Very specific:

    Use [Before(Assembly)] and [After(Assembly)] for shared context across test classes

    line 26
  10. Distinctive:

    Keep tests focused on a single behavior

    line 31
  11. Distinctive:

    Avoid testing multiple behaviors in one test method

    line 32
  12. Very specific:

    Use TUnit's fluent assertion syntax with await Assert.That()

    line 33
  13. Very specific:

    Avoid test interdependencies (use [DependsOn] attribute if needed)

    line 36
  14. Very specific:

    Use [Arguments] attribute for inline test data (equivalent to xUnit's [InlineData])

    line 40
  15. Very specific:

    Use [MethodData] for method-based test data (equivalent to xUnit's [MemberData])

    line 41
  16. Very specific:

    Use [ClassData] for class-based test data

    line 42
  17. Very specific:

    Create custom data sources by implementing ITestDataSource

    line 43
  18. Distinctive:

    Use meaningful parameter names in data-driven tests

    line 44
  19. Very specific:

    Use await Assert.That(value).IsEqualTo(expected) for value equality

    line 49
  20. Very specific:

    Use await Assert.That(value).IsSameReferenceAs(expected) for reference equality

    line 50
  21. Very specific:

    Use await Assert.That(value).IsTrue() or await Assert.That(value).IsFalse() for boolean conditions

    line 51
  22. Very specific:

    Use await Assert.That(collection).Contains(item) or await Assert.That(collection).DoesNotContain(item) for collections

    line 52
  23. Very specific:

    Use await Assert.That(value).Matches(pattern) for regex pattern matching

    line 53
  24. Very specific:

    Use await Assert.That(action).Throws<TException>() or await Assert.That(asyncAction).ThrowsAsync<TException>() to test exceptions

    line 54
  25. Very specific:

    Use .Or operator for alternative conditions: await Assert.That(value).IsEqualTo(1).Or.IsEqualTo(2)

    line 56
  26. Very specific:

    Use .Within(tolerance) for DateTime and numeric comparisons with tolerance

    line 57
  27. Distinctive:

    All assertions are asynchronous and must be awaited

    line 58
  28. Very specific:

    Use [Repeat(n)] to repeat tests multiple times

    line 62
  29. Very specific:

    Use [Retry(n)] for automatic retry on failure

    line 63
  30. Very specific:

    Use [ParallelLimit<T>] to control parallel execution limits

    line 64
  31. Very specific:

    Use [Skip("reason")] to skip tests conditionally

    line 65
  32. Very specific:

    Use [DependsOn(nameof(OtherTest))] to create test dependencies

    line 66
  33. Very specific:

    Use [Timeout(milliseconds)] to set test timeouts

    line 67
  34. Distinctive:

    Create custom attributes by extending TUnit's base attributes

    line 68
  35. Very specific:

    Use [Category("CategoryName")] for test categorization

    line 73
  36. Very specific:

    Use [DisplayName("Custom Test Name")] for custom test names

    line 74
  37. Very specific:

    Consider using TestContext for test diagnostics and information

    line 75
  38. Very specific:

    Use conditional attributes like custom [WindowsOnly] for platform-specific tests

    line 76
  39. Very specific:

    Use [NotInParallel] to disable parallel execution for specific tests

    line 81
  40. Very specific:

    Use [ParallelLimit<T>] with custom limit classes to control concurrency

    line 82
  41. Very specific:

    Use [Repeat(n)] with [ParallelLimit<T>] for load testing scenarios

    line 84

≈ “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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

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 [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.Equal with await Assert.That(actual).IsEqualTo(expected)
  • Replace Assert.True with await Assert.That(condition).IsTrue()
  • Replace Assert.Throws<T> with await 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.

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.