TUnit
Trigger On
- the repo uses TUnit
- you need to add, run, debug, or repair TUnit tests
- the repo uses Microsoft.Testing.Platform-based test execution
- the repo uses
ClassDataSource<...>(Shared = SharedType.PerTestSession), ParallelLimiter, TUnit.Playwright, or --treenode-filter
Value
- produce a concrete project delta: code, docs, config, tests, CI, or review artifact
- reduce ambiguity through explicit planning, verification, and final validation skills
- leave reusable project context so future tasks are faster and safer
Do Not Use For
- xUnit projects
- MSTest projects
- generic test strategy with no TUnit-specific mechanics
Inputs
- the nearest
AGENTS.md
- the test project file and package references
- the repo's current TUnit execution command
Quick Start
- Read the nearest
AGENTS.md and confirm scope and constraints.
- Run this skill's
Workflow through the Ralph Loop until outcomes are acceptable.
- Return the
Required Result Format with concrete artifacts and verification evidence.
Workflow
- Confirm the project really uses TUnit and not a different MTP-based framework.
- Read the repo's real
test command from AGENTS.md. If the repo has no explicit command yet, start with dotnet test PROJECT_OR_SOLUTION.
- Keep the TUnit execution model intact:
- tests are source-generated at build time
- tests run in parallel by default
- built-in analyzers should remain enabled
- Choose the fixture level deliberately:
- plain TUnit tests for isolated logic
- shared AppHost/Aspire fixtures for HTTP, SignalR, SSE, or UI flows
WebApplicationFactory layered over shared Aspire infra when tests need Host DI services, IGrainFactory, or other runtime internals
- Reuse expensive fixtures with
ClassDataSource<Fixture>(Shared = SharedType.PerTestSession) instead of booting distributed infrastructure per test.
- Fix isolation bugs instead of globally serializing the suite unless the repo already documented a justified exception.
- Run the narrowest useful scope first with
dotnet test ... -- --treenode-filter "...". Keep TUnit arguments after --.
- Capture useful failure evidence: host log dumps, focused console output, coverage files, and Playwright screenshots/HTML for UI tests.
- Use
[Test], [Arguments], hooks, and dependencies only when they make the scenario clearer, not because the framework allows it.
Bootstrap When Missing
If TUnit is requested but not configured yet:
- Detect current state:
rg -n "TUnit|Microsoft\\.Testing\\.Platform" -g '*.csproj' -g 'Directory.Build.*' .
- Add the minimal package set to the test project:
dotnet add TEST_PROJECT.csproj package TUnit
- add
Microsoft.NET.Test.Sdk only when the repo's chosen TUnit project shape requires it; do not blindly duplicate runner packages
- Keep the runner model explicit in
AGENTS.md and CI:
- record that the repo uses Microsoft.Testing.Platform-compatible execution for this test project
- record the exact
dotnet test TEST_PROJECT.csproj command the repo will use
- Add one small executable test using
[Test].
- Run
dotnet test TEST_PROJECT.csproj and return status: configured or status: improved.
- If the repo intentionally standardizes on xUnit or MSTest, return
status: not_applicable unless migration is explicitly requested.
Deliver
- TUnit tests that respect source generation and parallel execution
- commands that work in local and CI runs
- framework-specific verification guidance for the repo
- a fixture strategy that matches the actual test scope: logic-only, AppHost/API, Host DI/grains, or Playwright UI
Validate
- the command matches the repo's TUnit runner style
- focused runs use
--treenode-filter rather than VSTest-style --filter
- shared distributed fixtures use
SharedType.PerTestSession or an equivalent reuse pattern
- shared state is isolated or explicitly controlled
- built-in TUnit analyzers remain active
- coverage tooling matches Microsoft.Testing.Platform if coverage is enabled
- UI failures capture artifacts and server-side failures expose enough logs to avoid blind reruns
Test Harness
flowchart LR
A["TUnit task"] --> B{"What does the test need?"}
B -->|"Single component only"| C["Plain TUnit test"]
B -->|"HTTP / SignalR / resource graph"| D["Shared Aspire/AppHost fixture"]
B -->|"Host DI / grains / runtime services"| E["Shared Aspire/AppHost fixture + WebApplicationFactory"]
B -->|"Browser automation"| F["Shared Aspire/AppHost fixture + Playwright"]
C & D & E & F --> G["Run focused with --treenode-filter"]
G --> H["Capture logs, artifacts, and coverage"]
Ralph Loop
Use the Ralph Loop for every task, including docs, architecture, testing, and tooling work.
- Plan first (mandatory):
- analyze current state
- define target outcome, constraints, and risks
- write a detailed execution plan
- list final validation skills to run at the end, with order and reason
- Execute one planned step and produce a concrete delta.
- Review the result and capture findings with actionable next fixes.
- Apply fixes in small batches and rerun the relevant checks or review steps.
- Update the plan after each iteration.
- Repeat until outcomes are acceptable or only explicit exceptions remain.
- If a dependency is missing, bootstrap it or return
status: not_applicable with explicit reason and fallback path.
Required Result Format
status: complete | clean | improved | configured | not_applicable | blocked
plan: concise plan and current iteration step
actions_taken: concrete changes made
validation_skills: final skills run, or skipped with reasons
verification: commands, checks, or review evidence summary
remaining: top unresolved items or none
For setup-only requests with no execution, return status: configured and exact next commands.
Load References
references/patterns.md
references/migration.md
references/tunit.md
references/integration-testing.md
Running Tests
TUnit uses Microsoft.Testing.Platform. Use --treenode-filter for filtering (not --filter), and keep runner switches after --.
# Run all tests
dotnet test MySolution.sln
# Run one test project
dotnet test tests/MyProject.Tests/MyProject.Tests.csproj
# Filter by class
dotnet test tests/MyProject.Tests/MyProject.Tests.csproj -- --treenode-filter "/*/*/CalculatorTests/*"
# Filter by category
dotnet test tests/MyProject.Tests/MyProject.Tests.csproj -- --treenode-filter "/*/*/*/*[Category=Integration]"
# Coverage on Microsoft.Testing.Platform
dotnet test MySolution.sln -- --coverage --coverage-output coverage.cobertura.xml --coverage-output-format cobertura
# Raw runner help when the repo needs direct TUnit app switches
dotnet run --project tests/MyProject.Tests/MyProject.Tests.csproj -- --help
Filter syntax: /<Assembly>/<Namespace>/<Class>/<Test> with * wildcards. See references/patterns.md for full examples.
Example Requests
- "Run this TUnit project correctly."
- "Fix our TUnit CI command."
- "Add a regression test in TUnit without breaking parallelism."
1---2name: dotnet-tunit3description: Write, run, or repair .NET tests that use TUnit. Use when a repo uses `TUnit`, `TUnit.Playwright`, `[Test]`, `[Arguments]`, `ClassDataSource`, `SharedType.PerTestSession`, or Microsoft.Testing.Platform-based execution.4---56# TUnit78## Trigger On910- the repo uses TUnit11- you need to add, run, debug, or repair TUnit tests12- the repo uses Microsoft.Testing.Platform-based test execution13- the repo uses `ClassDataSource<...>(Shared = SharedType.PerTestSession)`, `ParallelLimiter`, `TUnit.Playwright`, or `--treenode-filter`1415## Value1617- produce a concrete project delta: code, docs, config, tests, CI, or review artifact18- reduce ambiguity through explicit planning, verification, and final validation skills19- leave reusable project context so future tasks are faster and safer2021## Do Not Use For2223- xUnit projects24- MSTest projects25- generic test strategy with no TUnit-specific mechanics2627## Inputs2829- the nearest `AGENTS.md`30- the test project file and package references31- the repo's current TUnit execution command3233## Quick Start34351. Read the nearest `AGENTS.md` and confirm scope and constraints.362. Run this skill's `Workflow` through the `Ralph Loop` until outcomes are acceptable.373. Return the `Required Result Format` with concrete artifacts and verification evidence.3839## Workflow40411. Confirm the project really uses TUnit and not a different MTP-based framework.422. Read the repo's real `test` command from `AGENTS.md`. If the repo has no explicit command yet, start with `dotnet test PROJECT_OR_SOLUTION`.433. Keep the TUnit execution model intact:44 - tests are source-generated at build time45 - tests run in parallel by default46 - built-in analyzers should remain enabled474. Choose the fixture level deliberately:48 - plain TUnit tests for isolated logic49 - shared AppHost/Aspire fixtures for HTTP, SignalR, SSE, or UI flows50 - `WebApplicationFactory` layered over shared Aspire infra when tests need Host DI services, `IGrainFactory`, or other runtime internals515. Reuse expensive fixtures with `ClassDataSource<Fixture>(Shared = SharedType.PerTestSession)` instead of booting distributed infrastructure per test.526. Fix isolation bugs instead of globally serializing the suite unless the repo already documented a justified exception.537. Run the narrowest useful scope first with `dotnet test ... -- --treenode-filter "..."`. Keep TUnit arguments after `--`.548. Capture useful failure evidence: host log dumps, focused console output, coverage files, and Playwright screenshots/HTML for UI tests.559. Use `[Test]`, `[Arguments]`, hooks, and dependencies only when they make the scenario clearer, not because the framework allows it.5657## Bootstrap When Missing5859If `TUnit` is requested but not configured yet:60611. Detect current state:62 - `rg -n "TUnit|Microsoft\\.Testing\\.Platform" -g '*.csproj' -g 'Directory.Build.*' .`632. Add the minimal package set to the test project:64 - `dotnet add TEST_PROJECT.csproj package TUnit`65 - add `Microsoft.NET.Test.Sdk` only when the repo's chosen TUnit project shape requires it; do not blindly duplicate runner packages663. Keep the runner model explicit in `AGENTS.md` and CI:67 - record that the repo uses Microsoft.Testing.Platform-compatible execution for this test project68 - record the exact `dotnet test TEST_PROJECT.csproj` command the repo will use694. Add one small executable test using `[Test]`.705. Run `dotnet test TEST_PROJECT.csproj` and return `status: configured` or `status: improved`.716. If the repo intentionally standardizes on xUnit or MSTest, return `status: not_applicable` unless migration is explicitly requested.7273## Deliver7475- TUnit tests that respect source generation and parallel execution76- commands that work in local and CI runs77- framework-specific verification guidance for the repo78- a fixture strategy that matches the actual test scope: logic-only, AppHost/API, Host DI/grains, or Playwright UI7980## Validate8182- the command matches the repo's TUnit runner style83- focused runs use `--treenode-filter` rather than VSTest-style `--filter`84- shared distributed fixtures use `SharedType.PerTestSession` or an equivalent reuse pattern85- shared state is isolated or explicitly controlled86- built-in TUnit analyzers remain active87- coverage tooling matches Microsoft.Testing.Platform if coverage is enabled88- UI failures capture artifacts and server-side failures expose enough logs to avoid blind reruns8990## Test Harness9192```mermaid93flowchart LR94 A["TUnit task"] --> B{"What does the test need?"}95 B -->|"Single component only"| C["Plain TUnit test"]96 B -->|"HTTP / SignalR / resource graph"| D["Shared Aspire/AppHost fixture"]97 B -->|"Host DI / grains / runtime services"| E["Shared Aspire/AppHost fixture + WebApplicationFactory"]98 B -->|"Browser automation"| F["Shared Aspire/AppHost fixture + Playwright"]99 C & D & E & F --> G["Run focused with --treenode-filter"]100 G --> H["Capture logs, artifacts, and coverage"]101```102103## Ralph Loop104105Use the Ralph Loop for every task, including docs, architecture, testing, and tooling work.1061071. Plan first (mandatory):108 - analyze current state109 - define target outcome, constraints, and risks110 - write a detailed execution plan111 - list final validation skills to run at the end, with order and reason1122. Execute one planned step and produce a concrete delta.1133. Review the result and capture findings with actionable next fixes.1144. Apply fixes in small batches and rerun the relevant checks or review steps.1155. Update the plan after each iteration.1166. Repeat until outcomes are acceptable or only explicit exceptions remain.1177. If a dependency is missing, bootstrap it or return `status: not_applicable` with explicit reason and fallback path.118119### Required Result Format120121- `status`: `complete` | `clean` | `improved` | `configured` | `not_applicable` | `blocked`122- `plan`: concise plan and current iteration step123- `actions_taken`: concrete changes made124- `validation_skills`: final skills run, or skipped with reasons125- `verification`: commands, checks, or review evidence summary126- `remaining`: top unresolved items or `none`127128For setup-only requests with no execution, return `status: configured` and exact next commands.129130## Load References131132- `references/patterns.md`133- `references/migration.md`134- `references/tunit.md`135- `references/integration-testing.md`136137## Running Tests138139TUnit uses Microsoft.Testing.Platform. Use `--treenode-filter` for filtering (not `--filter`), and keep runner switches after `--`.140141```bash142# Run all tests143dotnet test MySolution.sln144145# Run one test project146dotnet test tests/MyProject.Tests/MyProject.Tests.csproj147148# Filter by class149dotnet test tests/MyProject.Tests/MyProject.Tests.csproj -- --treenode-filter "/*/*/CalculatorTests/*"150151# Filter by category152dotnet test tests/MyProject.Tests/MyProject.Tests.csproj -- --treenode-filter "/*/*/*/*[Category=Integration]"153154# Coverage on Microsoft.Testing.Platform155dotnet test MySolution.sln -- --coverage --coverage-output coverage.cobertura.xml --coverage-output-format cobertura156157# Raw runner help when the repo needs direct TUnit app switches158dotnet run --project tests/MyProject.Tests/MyProject.Tests.csproj -- --help159```160161Filter syntax: `/<Assembly>/<Namespace>/<Class>/<Test>` with `*` wildcards. See `references/patterns.md` for full examples.162163## Example Requests164165- "Run this TUnit project correctly."166- "Fix our TUnit CI command."167- "Add a regression test in TUnit without breaking parallelism."