> Recommend or run the exact `dotnet test` command. ALWAYS use when the user asks to run, filter, or troubleshoot .NET tests or wants the precise command, flags, or argument order — the right syntax depends on the test platform (VSTest vs Microsoft.Testing.Platform) and SDK version and is specific class, category, or trait) via filters; a single framework in a multi-TFM project (`--framework`); TRX reports; crash or hang dumps; whether MTP args need the `--` separator (SDK 8/9) or pass directly (SDK 10+); diagnosing why `dotnet test` fails or uses wrong argument syntax. Detects the platform (VSTest vs MTP) and framework (MSTest/xUnit/NUnit/TUnit), then picks the matching command and filter flag (--filter, --filter-class, --filter-trait, --filter-query, code-testing-agent), iterating on failing tests without rebuilding (use mtp-hot-reload), CI/CD config, or debugging test logic.
npx skills add https://github.com/dotnet/skills --skill run-tests
Detect the test platform and framework, run tests, and apply filters using dotnet test.
writing-mstest-tests for MSTest, or general coding assistance for other frameworks)migrate-vstest-to-mtp)mtp-hot-reload)| Input | Required | Description |
|-------|----------|-------------|
| Project or solution path | No | Path to the test project (.csproj) or solution (.sln, .slnf, .slnx). Defaults to current directory. |
| Filter expression | No | Filter expression to select specific tests |
| Target framework | No | Target framework moniker to run against (e.g., net8.0) |
These are the most common agent mistakes. Internalize before proceeding:
| Rule | Why |
|------|-----|
| Do NOT use --logger trx for MTP projects | MTP uses --report-trx (requires the TrxReport extension package) |
| Do NOT use --report-trx for VSTest projects | VSTest uses --logger trx |
| Do NOT use -- --arg on .NET SDK 10+ | SDK 10+ passes MTP args directly: dotnet test --project . --report-trx |
| Do NOT omit -- on .NET SDK 8/9 with MTP | SDK 8/9 requires the separator: dotnet test -- --report-trx |
| Do NOT use --filter "ClassName=..." with xUnit v3 on MTP | xUnit v3 on MTP uses --filter-class, --filter-method, --filter-trait |
| Do NOT use bare positional path on SDK 10+ | Use --project <path> or --solution <path> instead |
| Do NOT use --blame for MTP projects | MTP uses --blame-crash and --blame-hang-timeout separately (each requires its extension package) |
| Do NOT use --collect "Code Coverage" for MTP | MTP uses --coverage (requires the CodeCoverage extension package) |
| Platform | SDK | Command pattern |
|----------|-----|----------------|
| VSTest | Any | dotnet test [<path>] [--filter <expr>] [--logger trx] |
| MTP | 8 or 9 | dotnet test [<path>] -- <MTP_ARGS> |
| MTP | 10+ | dotnet test --project <path> <MTP_ARGS> |
Detection files to always check (in order): global.json -> .csproj -> Directory.Build.props -> Directory.Packages.props
If the prompt names a subset of tests (e.g., "integration tests", "smoke tests", a specific class, a specific TFM), plan to apply the matching filter / --framework in Step 3 — do not run the whole suite.
dotnet --version in the project directory to determine the SDK version. This accounts for global.json SDK pinning.global.json — on .NET SDK 10+, "test": { "runner": "Microsoft.Testing.Platform" } is the authoritative MTP signal. If present, the project uses MTP and SDK 10+ syntax (no -- separator)..csproj, Directory.Build.props, and Directory.Packages.props for framework packages and MTP properties. Always check all three files — MTP properties are frequently set in Directory.Build.props rather than individual .csproj files.platform-detection skill.What to look for in each file:
| File | Look for | Indicates |
|------|----------|-----------|
| global.json | "test": { "runner": "Microsoft.Testing.Platform" } | MTP on SDK 10+ |
| global.json | "sdk": { "version": "..." } | SDK version (determines -- separator behavior) |
| .csproj | <TestingPlatformDotnetTestSupport>true | MTP on SDK 8/9 |
| .csproj | MSTest, xunit.v3, NUnit, TUnit packages | Framework identity |
| .csproj | Microsoft.NET.Test.Sdk + test adapter | VSTest (unless overridden by MTP signals above) |
| .csproj | <TargetFrameworks> (plural) | Multi-TFM — may need --framework |
| Directory.Build.props | <TestingPlatformDotnetTestSupport>true | MTP on SDK 8/9 (often set here, not in .csproj) |
| Directory.Packages.props | Centrally managed test package versions | Framework identity for CPM repos |
Quick detection summary:
| Signal | Means |
|--------|-------|
| global.json has "test": { "runner": "Microsoft.Testing.Platform" } | MTP on SDK 10+ — pass args directly, no -- |
| <TestingPlatformDotnetTestSupport>true in csproj or Directory.Build.props | MTP on SDK 8/9 — pass args after -- |
| Neither signal present | VSTest |
dotnet test [<PROJECT> | <SOLUTION> | <DIRECTORY> | <DLL> | <EXE>]
Common flags:
| Flag | Description |
|------|-------------|
| --framework <TFM> | Target a specific framework in multi-TFM projects (e.g., net8.0) |
| --no-build | Skip build, use previously built output |
| --filter <EXPRESSION> | Run selected tests (see Step 3) |
| --logger trx | Generate TRX results file |
| --collect "Code Coverage" | Collect code coverage using Microsoft Code Coverage (built-in, always available) |
| --blame | Enable blame mode to detect tests that crash the host |
| --blame-crash | Collect a crash dump when the test host crashes |
| --blame-hang-timeout <duration> | Abort test if it hangs longer than duration (e.g., 5min) |
| -v <level> | Verbosity: quiet, minimal, normal, detailed, diagnostic |
With <TestingPlatformDotnetTestSupport>true</TestingPlatformDotnetTestSupport>, dotnet test bridges to MTP but uses VSTest-style argument parsing. MTP-specific arguments must be passed after --:
dotnet test [<PROJECT> | <SOLUTION> | <DIRECTORY> | <DLL> | <EXE>] -- <MTP_ARGUMENTS>
With the global.json runner set to Microsoft.Testing.Platform, dotnet test natively understands MTP arguments without --:
dotnet test
[--project <PROJECT_OR_DIRECTORY>]
[--solution <SOLUTION_OR_DIRECTORY>]
[--test-modules <EXPRESSION>]
[<MTP_ARGUMENTS>]
Examples:
# Run all tests in a project
dotnet test --project path/to/MyTests.csproj
# Run all tests in a directory containing a project
dotnet test --project path/to/
# Run all tests in a solution (sln, slnf, slnx)
dotnet test --solution path/to/MySolution.sln
dotnet test --solution path/to/MySolution.slnf
dotnet test --solution path/to/MySolution.slnx
# Run all tests in a directory containing a solution
dotnet test --solution path/to/
# Run with MTP flags
dotnet test --project path/to/MyTests.csproj --report-trx --blame-hang-timeout 5min
> Note: The .NET 10+ dotnet test syntax does not accept a bare positional argument like the VSTest syntax. Use --project, --solution, or --test-modules to specify the target.
These flags apply to MTP on both SDK versions. On SDK 8/9, pass after --; on SDK 10+, pass directly.
> Important: dotnet test/MSBuild flags such as --framework, --no-build, --configuration, and --verbosity are consumed by dotnet test itself (they drive restore/build/host selection) and always go BEFORE --, regardless of platform or SDK. Only MTP test-platform arguments go after -- on SDK 8/9. For example: dotnet test --framework net9.0 -- --report-trx (built-in flag before --, MTP extension flag after).
Built-in flags (always available):
| Flag | Description |
|------|-------------|
| --results-directory <DIR> | Directory for test result output |
| --diagnostic | Enable diagnostic logging for the test platform |
| --diagnostic-output-directory <DIR> | Directory for diagnostic log output |
Extension-dependent flags (require the corresponding extension package to be registered):
| Flag | Requires | Description |
|------|----------|-------------|
| --filter <EXPRESSION> | Framework-specific (not all frameworks support this) | Run selected tests (see Step 3) |
| --report-trx | Microsoft.Testing.Extensions.TrxReport | Generate TRX results file |
| --report-trx-filename <FILE> | Microsoft.Testing.Extensions.TrxReport | Set TRX output filename |
| --blame-hang-timeout <duration> | Microsoft.Testing.Extensions.HangDump | Abort test if it hangs longer than duration (e.g., 5min) |
| --blame-crash | Microsoft.Testing.Extensions.CrashDump | Collect a crash dump when the test host crashes |
| --coverage | Microsoft.Testing.Extensions.CodeCoverage | Collect code coverage using Microsoft Code Coverage |
> Some frameworks (e.g., MSTest) bundle common extensions by default. Others may require explicit package references. If a flag is not recognized, check that the corresponding extension package is referenced in the project.
MTP test projects are standalone executables. Beyond dotnet test, they can be run directly:
# Build and run
dotnet run --project <PROJECT_PATH>
# Run a previously built DLL
dotnet exec <PATH_TO_DLL>
# Run the executable directly (Windows)
<PATH_TO_EXE>
These alternative invocations accept MTP command line arguments directly (no -- separator needed).
See the filter-syntax skill for the complete filter syntax for each platform and framework combination. Key points:
dotnet test --filter <EXPRESSION> with =, !=, ~, !~ operators--filter syntax as VSTest; pass after -- on SDK 8/9, directly on SDK 10+--filter-class, --filter-method, --filter-trait (not VSTest expression syntax). For a single combined expression (e.g., a class-name pattern AND a trait), use --filter-query with the xUnit v3 query filter language: path segments /<assembly>/<namespace>/<class>/<method> with * wildcards and a [Trait=Value] qualifier — for example dotnet test -- --filter-query "/*/*/*IntegrationTests*/*[Category=Smoke]". See the filter-syntax skill for the full query language.--treenode-filter with path-based syntaxWhen the prompt names a subset of tests by category (e.g., "integration tests", "unit tests", "smoke tests", "fast tests"), do not run all tests — translate the user's vocabulary into the platform-appropriate filter:
| Framework | Attribute | Filter property |
|-----------|-----------|-----------------|
| MSTest | [TestCategory("Integration")] | TestCategory |
| NUnit | [Category("Integration")] | TestCategory (mapped) |
| xUnit v2 | [Trait("Category", "Integration")] | Category |
| xUnit v3 | [Trait("Category", "Integration")] | Category (use --filter-trait) |
| TUnit | [Category("Integration")] | Category |
| Platform | SDK | Command |
|----------|-----|---------|
| VSTest (MSTest) | any | dotnet test --filter "TestCategory=Integration" |
| MTP (MSTest) | 8 or 9 | dotnet test -- --filter "TestCategory=Integration" |
| MTP (MSTest) | 10+ | dotnet test --filter "TestCategory=Integration" |
| MTP (xUnit v3) | 8 or 9 | dotnet test -- --filter-trait "Category=Integration" |
| MTP (xUnit v3) | 10+ | dotnet test --filter-trait "Category=Integration" |
| MTP (TUnit) | 8 or 9 | dotnet test -- --treenode-filter "/*/*/*/*[Category=Integration]" |
--filter "FullyQualifiedName~Integration").dotnet test invocation was used for the detected platform and SDK version| Pitfall | Solution |
|---------|----------|
| Missing Microsoft.NET.Test.Sdk in a VSTest project | Tests won't be discovered. Add <PackageReference Include="Microsoft.NET.Test.Sdk" /> |
| Using VSTest --filter syntax with xUnit v3 on MTP | xUnit v3 on MTP uses --filter-class, --filter-method, etc. -- not the VSTest expression syntax |
| Passing MTP args without -- on .NET SDK 8/9 | Before .NET 10, MTP args must go after --: dotnet test -- --report-trx |
| Using -- --arg separator on .NET SDK 10+ | SDK 10+ passes MTP args directly — do NOT use -- separator |
| Using --logger trx for MTP or --report-trx for VSTest | Each platform has its own TRX flag — check the Critical Rules table |
| Only checking .csproj for MTP signals | Always check Directory.Build.props and Directory.Packages.props too — MTP properties are frequently set there |
| Using bare positional path argument on SDK 10+ | SDK 10+ requires named flags: --project <path> or --solution <path> |
Common error messages and how to resolve them:
| Error | Cause | Fix |
|-------|-------|-----|
| No test is available or No test matches the given testcase filter | Wrong filter syntax for the platform/framework, or tests not discovered | Verify filter syntax matches the platform (see filter-syntax skill). For discovery issues, check that the test SDK and adapter packages are installed |
| The --report-trx option is unrecognized | MTP extension package not referenced, or using MTP flag on a VSTest project | Add <PackageReference Include="Microsoft.Testing.Extensions.TrxReport" /> for MTP, or use --logger trx for VSTest |
| The --blame-hang-timeout option is unrecognized | Missing HangDump extension on MTP | Add <PackageReference Include="Microsoft.Testing.Extensions.HangDump" /> |
| error NETSDK1045: The current .NET SDK does not support targeting .NET X.0 | SDK version in global.json doesn't match the project's target framework | Update global.json SDK version or install the required SDK |
| The test runner process exited with non-zero exit code | MTP test host crashed or test failure | Run with --blame-crash (MTP) or --blame (VSTest) to collect a crash dump for diagnosis |
| No test source files were found / No test project found | dotnet test can't find a test project in the given path | Specify the path explicitly: dotnet test <path/to/project.csproj> (VSTest) or dotnet test --project <path> (SDK 10+) |
| Tests discovered but 0 executed | Filter expression matches no tests | Double-check filter property names and values. Common typo: TestCategory (MSTest) vs Category (NUnit) vs trait syntax (xUnit) |
| Using -- for MTP args on .NET SDK 10+ | On .NET 10+, MTP args are passed directly: dotnet test --project . --blame-hang-timeout 5min — do NOT use -- --blame-hang-timeout |
| Multi-TFM project runs tests for all frameworks | Use --framework <TFM> to target a specific framework |
| global.json runner setting ignored | Requires .NET 10+ SDK. On older SDKs, use <TestingPlatformDotnetTestSupport> MSBuild property instead |
| TUnit --treenode-filter not recognized | TUnit is MTP-only. On .NET SDK 10+ use dotnet test; on older SDKs use dotnet run since VSTest-mode dotnet test does not support TUnit |
Use when implementation is complete, all tests pass, and you need to decide how to integrate the work - guides completion of development work by presenting structured options for merge, PR, or cleanup
Comprehensive GitHub release orchestration with AI swarm coordination for automated versioning, testing, deployment, and rollback management
Migrate test files from `as` type assertions to @total-typescript/shoehorn. Use when user mentions shoehorn, wants to replace `as` in tests, or needs partial test data.
Modern JavaScript/TypeScript development with Bun runtime. Covers package management, bundling, testing, and migration from Node.js. Use when working with Bun, optimizing JS/TS development speed, or migrating from Node.js to Bun.
You are a dependency management expert specializing in safe, incremental upgrades of project dependencies. Plan and execute dependency updates with minimal risk, proper testing, and clear migration pa
Master systematic debugging techniques, profiling tools, and root cause analysis to efficiently track down bugs across any codebase or technology stack. Use when investigating bugs, performance issues, or unexpected behavior.
Opinionated backend development standards for Node.js + Express + TypeScript microservices. Covers layered architecture, BaseController pattern, dependency injection, Prisma repositories, Zod validation, unifiedConfig, Sentry error tracking, async safety, and testing discipline.
Best practices for writing JavaScript/TypeScript tests using Jest, including mocking strategies, test structure, and common patterns.
Take dotnet/run-tests from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.