{
  "schema": "https://ai-atoms.com/schemas/skill-v1.json",
  "type": "skill",
  "id": "skill/run-tests",
  "version": "1.0.1",
  "name": "run-tests",
  "description": "ALWAYS USE before running .NET tests or answering with a test command or flags. Trigger on \"run the tests\", \"exact dotnet test command\", one test/class/category/trait/target framework, combined filters, `--filter-query`, `--no-build`, `--diag`, diagnostic logs, TRX, coverage collection, crash/hang dumps, filter errors, or unrecognized options. Chooses repository-compatible classic, VSTest, bridged MTP, or native MTP syntax for MSTest/xUnit/NUnit/TUnit. DO NOT USE for platform identification alone (platform-detection), writing or debugging test code, interpreting an existing coverage report, CI investigation, migration, or a persistent hot reload/watch loop.",
  "system_prompt_fragment": "# Run .NET Tests\n\nDetect the test platform and framework, run tests, and apply filters using `dotnet test`.\n\n## When to Use\n\n- User wants to run tests in a .NET project\n- User needs to run a subset of tests using filters\n- User needs help detecting which test platform (VSTest vs MTP) or framework is in use\n- User wants to understand the correct filter syntax for their setup\n\n## When Not to Use\n\n- User needs to write or generate test code (use `writing-mstest-tests` for MSTest, or general coding assistance for other frameworks)\n- User needs to migrate from VSTest to MTP (use `migrate-vstest-to-mtp`)\n- User wants to iterate on failing tests without rebuilding (use `mtp-hot-reload`)\n- User needs CI/CD pipeline configuration (use CI-specific skills)\n- User needs to debug a test (use debugging skills)\n\n## Inputs\n\n| Input | Required | Description |\n|-------|----------|-------------|\n| Project or solution path | No | Path to the test project (.csproj) or solution (.sln). Defaults to current directory. |\n| Filter expression | No | Filter expression to select specific tests |\n| Target framework | No | Target framework moniker to run against (e.g., `net8.0`) |\n\n## Critical Rules — Avoid Cross-Platform Mistakes\n\nThese are the most common agent mistakes. Internalize before proceeding:\n\n| Rule | Why |\n|------|-----|\n| **Do NOT use `--logger trx`** for MTP projects | MTP uses `--report-trx` (requires the TrxReport extension package) |\n| **Do NOT use `--report-trx`** for VSTest projects | VSTest uses `--logger trx` |\n| **Do NOT use `-- --arg`** on .NET SDK 10+ | SDK 10+ passes MTP args directly: `dotnet test --project . --report-trx` |\n| **Do NOT omit `--`** on .NET SDK 8/9 with MTP | SDK 8/9 requires the separator: `dotnet test -- --report-trx` |\n| **Do NOT use `--filter \"ClassName=...\"`** with xUnit v3 on MTP | xUnit v3 on MTP uses `--filter-class`, `--filter-method`, `--filter-trait` |\n| **Do NOT use bare positional path** on SDK 10+ | Use `--project <path>` or `--solution <path>` instead |\n| **Do NOT use `--blame`** for MTP projects | MTP uses `--blame-crash` and `--blame-hang-timeout` separately (each requires its extension package) |\n| **Do NOT use `--collect \"Code Coverage\"`** for MTP | MTP uses `--coverage` (requires the CodeCoverage extension package) |\n\n## Workflow\n\n### Quick Reference\n\n| Platform | SDK | Command pattern |\n|----------|-----|----------------|\n| VSTest | Any | `dotnet test [<path>] [--filter <expr>] [--logger trx]` |\n| MTP | 8 or 9 | `dotnet test [<path>] -- <MTP_ARGS>` |\n| MTP | 10+ | `dotnet test --project <path> <MTP_ARGS>` |\n\n**Detection files to always check** (in order): `global.json` -> `.csproj` -> `Directory.Build.props` -> `Directory.Packages.props`\n\n**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](#step-3-run-filtered-tests) — do not run the whole suite.\n\n### Step 1: Detect the test platform and framework\n\n1. Run `dotnet --version` in the project directory to determine the SDK version. This accounts for `global.json` SDK pinning.\n2. Read `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).\n3. Read `.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.\n4. For full detection logic (SDK 8/9 signals, framework identification), see the `platform-detection` skill.\n\n**What to look for in each file:**\n\n| File | Look for | Indicates |\n|------|----------|-----------|\n| `global.json` | `\"test\": { \"runner\": \"Microsoft.Testing.Platform\" }` | MTP on SDK 10+ |\n| `global.json` | `\"sdk\": { \"version\": \"...\" }` | SDK version (determines `--` separator behavior) |\n| `.csproj` | `<TestingPlatformDotnetTestSupport>true` | MTP on SDK 8/9 |\n| `.csproj` | `MSTest`, `xunit.v3`, `NUnit`, `TUnit` packages | Framework identity |\n| `.csproj` | `Microsoft.NET.Test.Sdk` + test adapter | VSTest (unless overridden by MTP signals above) |\n| `.csproj` | `<TargetFrameworks>` (plural) | Multi-TFM — may need `--framework` |\n| `Directory.Build.props` | `<TestingPlatformDotnetTestSupport>true` | MTP on SDK 8/9 (often set here, not in .csproj) |\n| `Directory.Packages.props` | Centrally managed test package versions | Framework identity for CPM repos |\n\n**Quick detection summary:**\n\n| Signal | Means |\n|--------|-------|\n| `global.json` has `\"test\": { \"runner\": \"Microsoft.Testing.Platform\" }` | **MTP on SDK 10+** — pass args directly, no `--` |\n| `<TestingPlatformDotnetTestSupport>true` in csproj or Directory.Build.props | **MTP on SDK 8/9** — pass args after `--` |\n| Neither signal present | **VSTest** |\n\n### Step 2: Run tests\n\n#### VSTest (any .NET SDK version)\n\n```bash\ndotnet test [<PROJECT> | <SOLUTION> | <DIRECTORY> | <DLL> | <EXE>]\n```\n\nCommon flags:\n\n| Flag | Description |\n|------|-------------|\n| `--framework <TFM>` | Target a specific framework in multi-TFM projects (e.g., `net8.0`) |\n| `--no-build` | Skip build, use previously built output |\n| `--filter <EXPRESSION>` | Run selected tests (see [Step 3](#step-3-run-filtered-tests)) |\n| `--logger trx` | Generate TRX results file |\n| `--collect \"Code Coverage\"` | Collect code coverage using Microsoft Code Coverage (built-in, always available) |\n| `--blame` | Enable blame mode to detect tests that crash the host |\n| `--blame-crash` | Collect a crash dump when the test host crashes |\n| `--blame-hang-timeout <duration>` | Abort test if it hangs longer than duration (e.g., `5min`) |\n| `-v <level>` | Verbosity: `quiet`, `minimal`, `normal`, `detailed`, `diagnostic` |\n\n#### MTP with .NET SDK 8 or 9\n\nWith `<TestingPlatformDotnetTestSupport>true</TestingPlatformDotnetTestSupport>`, `dotnet test` bridges to MTP but uses VSTest-style argument parsing. MTP-specific arguments must be passed after `--`:\n\n```bash\ndotnet test [<PROJECT> | <SOLUTION> | <DIRECTORY> | <DLL> | <EXE>] -- <MTP_ARGUMENTS>\n```\n\n#### MTP with .NET SDK 10+\n\nWith the `global.json` runner set to `Microsoft.Testing.Platform`, `dotnet test` natively understands MTP arguments without `--`:\n\n```bash\ndotnet test\n    [--project <PROJECT_OR_DIRECTORY>]\n    [--solution <SOLUTION_OR_DIRECTORY>]\n    [--test-modules <EXPRESSION>]\n    [<MTP_ARGUMENTS>]\n```\n\nExamples:\n\n```bash\n# Run all tests in a project\ndotnet test --project path/to/MyTests.csproj\n\n# Run all tests in a directory containing a project\ndotnet test --project path/to/\n\n# Run all tests in a solution (sln, slnf, slnx)\ndotnet test --solution path/to/MySolution.sln\n\n# Run all tests in a directory containing a solution\ndotnet test --solution path/to/\n\n# Run with MTP flags\ndotnet test --project path/to/MyTests.csproj --report-trx --blame-hang-timeout 5min\n```\n\n> **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.\n\n#### Common MTP flags\n\nThese flags apply to MTP on both SDK versions. On SDK 8/9, pass after `--`; on SDK 10+, pass directly.\n\n> **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).\n\n**Built-in flags (always available):**\n\n| Flag | Description |\n|------|-------------|\n| `--results-directory <DIR>` | Directory for test result output |\n| `--diagnostic` | Enable diagnostic logging for the test platform |\n| `--diagnostic-output-directory <DIR>` | Directory for diagnostic log output |\n\n**Extension-dependent flags (require the corresponding extension package to be registered):**\n\n| Flag | Requires | Description |\n|------|----------|-------------|\n| `--filter <EXPRESSION>` | Framework-specific (not all frameworks support this) | Run selected tests (see [Step 3](#step-3-run-filtered-tests)) |\n| `--report-trx` | `Microsoft.Testing.Extensions.TrxReport` | Generate TRX results file |\n| `--report-trx-filename <FILE>` | `Microsoft.Testing.Extensions.TrxReport` | Set TRX output filename |\n| `--blame-hang-timeout <duration>` | `Microsoft.Testing.Extensions.HangDump` | Abort test if it hangs longer than duration (e.g., `5min`) |\n| `--blame-crash` | `Microsoft.Testing.Extensions.CrashDump` | Collect a crash dump when the test host crashes |\n| `--coverage` | `Microsoft.Testing.Extensions.CodeCoverage` | Collect code coverage using Microsoft Code Coverage |\n\n> 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.\n\n#### Alternative MTP invocations\n\nMTP test projects are standalone executables. Beyond `dotnet test`, they can be run directly:\n\n```bash\n# Build and run\ndotnet run --project <PROJECT_PATH>\n\n# Run a previously built DLL\ndotnet exec <PATH_TO_DLL>\n\n# Run the executable directly (Windows)\n<PATH_TO_EXE>\n```\n\nThese alternative invocations accept MTP command line arguments directly (no `--` separator needed).\n\n### Step 3: Run filtered tests\n\nSee the `filter-syntax` skill for the complete filter syntax for each platform and framework combination. Key points:\n\n- **VSTest** (MSTest, xUnit v2, NUnit): `dotnet test --filter <EXPRESSION>` with `=`, `!=`, `~`, `!~` operators\n- **MTP -- MSTest and NUnit**: Same `--filter` syntax as VSTest; pass after `--` on SDK 8/9, directly on SDK 10+\n- **MTP -- xUnit v3**: Uses `--filter-class`, `--filter-method`, `--filter-trait` (not VSTest expression syntax)\n- **MTP -- TUnit**: Uses `--treenode-filter` with path-based syntax\n\n#### When the user names a test category, trait, or group\n\nWhen 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:\n\n1. **Inspect the test source files** for filter-attribute annotations that match the named group:\n\n   | Framework | Attribute | Filter property |\n   |-----------|-----------|-----------------|\n   | MSTest | `[TestCategory(\"Integration\")]` | `TestCategory` |\n   | NUnit | `[Category(\"Integration\")]` | `TestCategory` (mapped) |\n   | xUnit v2 | `[Trait(\"Category\", \"Integration\")]` | `Category` |\n   | xUnit v3 | `[Trait(\"Category\", \"Integration\")]` | `Category` (use `--filter-trait`) |\n   | TUnit | `[Category(\"Integration\")]` | `Category` |\n\n2. **Build the filter expression** and combine it with the platform-correct invocation. For \"run the integration tests\" against an MSTest project:\n\n   | Platform | SDK | Command |\n   |----------|-----|---------|\n   | VSTest (MSTest) | any | `dotnet test --filter \"TestCategory=Integration\"` |\n   | MTP (MSTest) | 8 or 9 | `dotnet test -- --filter \"TestCategory=Integration\"` |\n   | MTP (MSTest) | 10+ | `dotnet test --filter \"TestCategory=Integration\"` |\n   | MTP (xUnit v3) | 8 or 9 | `dotnet test -- --filter-trait \"Category=Integration\"` |\n   | MTP (xUnit v3) | 10+ | `dotnet test --filter-trait \"Category=Integration\"` |\n   | MTP (TUnit) | 8 or 9 | `dotnet test -- --treenode-filter \"/*/*/*/*[Category=Integration]\"` |\n\n3. If you cannot find a matching attribute, ask the user to confirm the category name or fall back to a name-pattern filter (e.g., `--filter \"FullyQualifiedName~Integration\"`).\n\n## Validation\n\n- [ ] Test platform (VSTest or MTP) was correctly identified\n- [ ] Test framework (MSTest, xUnit, NUnit, TUnit) was correctly identified\n- [ ] Correct `dotnet test` invocation was used for the detected platform and SDK version\n- [ ] When the user named a test category/trait/group, the appropriate filter was applied (not \"run all tests\")\n- [ ] Filter expressions used the syntax appropriate for the platform and framework\n- [ ] Test results were clearly reported to the user\n\n## Common Pitfalls\n\n| Pitfall | Solution |\n|---------|----------|\n| Missing `Microsoft.NET.Test.Sdk` in a VSTest project | Tests won't be discovered. Add `<PackageReference Include=\"Microsoft.NET.Test.Sdk\" />` |\n| Using VSTest `--filter` syntax with xUnit v3 on MTP | xUnit v3 on MTP uses `--filter-class`, `--filter-method`, etc. -- not the VSTest expression syntax |\n| Passing MTP args without `--` on .NET SDK 8/9 | Before .NET 10, MTP args must go after `--`: `dotnet test -- --report-trx` |\n| Using `-- --arg` separator on .NET SDK 10+ | SDK 10+ passes MTP args directly — do NOT use `--` separator |\n| Using `--logger trx` for MTP or `--report-trx` for VSTest | Each platform has its own TRX flag — check the Critical Rules table |\n| Only checking `.csproj` for MTP signals | Always check `Directory.Build.props` and `Directory.Packages.props` too — MTP properties are frequently set there |\n| Using bare positional path argument on SDK 10+ | SDK 10+ requires named flags: `--project <path>` or `--solution <path>` |\n\n## Troubleshooting\n\nCommon error messages and how to resolve them:\n\n| Error | Cause | Fix |\n|-------|-------|-----|\n| `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 |\n| `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 |\n| `The --blame-hang-timeout option is unrecognized` | Missing HangDump extension on MTP | Add `<PackageReference Include=\"Microsoft.Testing.Extensions.HangDump\" />` |\n| `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 |\n| `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 |\n| `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+) |\n| 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) |\n| 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` |\n| Multi-TFM project runs tests for all frameworks | Use `--framework <TFM>` to target a specific framework |\n| `global.json` runner setting ignored | Requires .NET 10+ SDK. On older SDKs, use `<TestingPlatformDotnetTestSupport>` MSBuild property instead |\n| 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 |",
  "applicable_domains": [
    "code",
    "dotnet",
    "engineering"
  ],
  "invocation": [
    "/run-tests"
  ],
  "tags": [
    "dotnet-test",
    "dotnet",
    "csharp",
    "microsoft"
  ],
  "authored_by": "anthropics",
  "source_url": "https://github.com/dotnet/skills/blob/main/plugins/dotnet-test/skills/run-tests/SKILL.md",
  "lifecycle": "stable",
  "category": "dotnet",
  "provenance": {
    "source": "dotnet/skills",
    "source_url": "https://github.com/dotnet/skills/blob/main/plugins/dotnet-test/skills/run-tests/SKILL.md",
    "author": "Microsoft / .NET Foundation",
    "license": "MIT",
    "notes": "Imported by scripts/import-anthropic-skills.py."
  }
}