# Handling .NET SDK Version Differences in `dotnet test` Argument Parsing

> Master dotnet test argument parsing with .NET SDK version differences. Learn how SDK versions affect argument handling and ensure smooth test execution.

- Repository: [.NET Platform/skills](https://github.com/dotnet/skills)
- Tags: how-to-guide
- Published: 2026-07-11

---

**The `dotnet test` command adapts its CLI parsing rules based on the active .NET SDK version, requiring a `--` separator for Microsoft Testing Platform arguments in SDK 8 and 9 while accepting them as first-class options in SDK 10 and later.**

The `dotnet/skills` repository provides detailed guidance on handling .NET SDK version differences in `dotnet test` argument parsing to ensure reliable test execution across different SDK generations. Understanding these parsing rules is essential when working with the **Microsoft Testing Platform (MTP)** or legacy **VSTest** runners, as incorrect argument placement can lead to silent failures or empty test runs.

## SDK Version Detection Strategy

The **platform-detection** skill determines the active SDK version by executing `dotnet --version`, which respects any [`global.json`](https://github.com/dotnet/skills/blob/main/global.json) file present in the repository. According to [`plugins/dotnet-test/skills/platform-detection/SKILL.md`](https://github.com/dotnet/skills/blob/main/plugins/dotnet-test/skills/platform-detection/SKILL.md), this version check is the foundation for the *run-tests* skill's conditional parsing logic.

The detected version drives whether the skill injects the `--` separator when constructing command strings for MTP-based test runs.

## Argument Parsing Rules by SDK Version

The `dotnet test` CLI implements different parsing strategies depending on the SDK generation. The run-tests skill documentation in [`plugins/dotnet-test/skills/run-tests/SKILL.md`](https://github.com/dotnet/skills/blob/main/plugins/dotnet-test/skills/run-tests/SKILL.md) (lines 55-71) defines these boundaries:

### SDK 8 and 9: Separator Required

For .NET SDK versions 8 and 9, **MTP arguments must follow a `--` separator**. The separator demarcates where built-in `dotnet test` options end and platform-specific arguments begin.

```bash
dotnet test --project tests/MyApp.Tests.csproj -- --report-trx

```

In this example, `--project` is a built-in driver option parsed before the separator, while `--report-trx` is an MTP-specific argument passed after the separator.

### SDK 10 and Later: Direct Argument Parsing

Starting with .NET SDK 10, MTP arguments are treated as first-class options. The double-dash separator is **not required** when passing platform-specific flags.

```bash
dotnet test --project tests/MyApp.Tests.csproj --report-trx

```

### Built-in Flag Placement Rules

Regardless of SDK version, **built-in `dotnet test` flags** (e.g., `--framework`, `--no-build`, `--configuration`) must always precede the `--` separator when one is used. This rule applies universally across all SDK versions documented in the run-tests skill.

## Platform-Specific Syntax: VSTest vs. MTP

The argument parsing behavior differs significantly between the classic VSTest runner and the modern Microsoft Testing Platform.

### VSTest Classic Behavior

VSTest arguments are passed directly to the underlying `vstest.console` and do not require the `--` separator, regardless of SDK version. The syntax remains consistent across all supported SDKs:

```bash
dotnet test tests/LegacyTests.csproj --filter "TestCategory=Integration"

```

### Microsoft Testing Platform Behavior

MTP (used by xUnit v3, MSTest, and TUnit) requires SDK-aware parsing:

- **SDK 8/9**: Prefix MTP arguments with `--`
  ```bash
  dotnet test -- --filter-trait "Category=Integration"
  ```

- **SDK 10+**: Pass arguments directly
  ```bash
  dotnet test --project Tests/MyTests.csproj --filter-trait "Category=Integration"
  ```

The run-tests skill documentation (lines 240-246 in [`plugins/dotnet-test/skills/run-tests/SKILL.md`](https://github.com/dotnet/skills/blob/main/plugins/dotnet-test/skills/run-tests/SKILL.md)) also notes that filter syntax varies by platform, such as using `--filter-query` for xUnit v3 specific queries.

## Practical Code Examples

### Running MTP Tests on SDK 9 (Requires Separator)

```bash
dotnet test --project tests/MyApp.Tests.csproj -- --report-trx

```

- `--project` is a built-in `dotnet test` option placed before `--`
- `--report-trx` is an MTP argument placed after the separator

### Running MTP Tests on SDK 10+ (No Separator)

```bash
dotnet test --project tests/MyApp.Tests.csproj --report-trx

```

All arguments are parsed at the top level by the SDK 10+ driver.

### Using Filter Queries with xUnit v3 on SDK 10+

```bash
dotnet test --project tests/XUnitV3Tests.csproj --filter-query "/*/*/*IntegrationTests*/*[Category=Smoke]"

```

### VSTest Syntax (Consistent Across SDKs)

```bash
dotnet test tests/LegacyTests.csproj --filter "TestCategory=Integration"

```

## Why SDK-Aware Parsing Matters

**Correct test discovery**: Using the wrong separator causes MTP arguments to be ignored by the driver, resulting in empty test runs or failures to locate specific tests.

**Consistent CI behavior**: Automated pipelines must apply the same parsing rules as local development environments. Mismatched SDK versions between CI agents and developer machines produce divergent outcomes unless the execution logic adapts dynamically.

**Future-proofing**: As documented in [`plugins/dotnet-test/skills/coverage-analysis/SKILL.md`](https://github.com/dotnet/skills/blob/main/plugins/dotnet-test/skills/coverage-analysis/SKILL.md), the same SDK version checks influence coverage-related arguments (e.g., `--coverage` placement). The skill automatically switches parsing modes, ensuring scripts remain portable across SDK upgrades without manual intervention.

## Summary

- **Always detect the SDK version** using `dotnet --version` (respecting [`global.json`](https://github.com/dotnet/skills/blob/main/global.json)) before constructing commands.
- **Insert `--` only for SDK 8/9** when passing MTP-specific flags; omit it for SDK 10+.
- **Place built-in options before the separator** on all SDK versions where a separator is used.
- **VSTest arguments require no separator** regardless of SDK version.

## Frequently Asked Questions

### What is the purpose of the `--` separator in `dotnet test`?

The `--` separator demarcates the boundary between built-in `dotnet test` driver options and Microsoft Testing Platform-specific arguments. In SDK 8 and 9, arguments placed after `--` are passed directly to the test platform rather than being parsed by the `dotnet test` CLI driver. SDK 10+ treats MTP arguments as first-class options, making the separator optional.

### How do I determine which parsing rules apply to my environment?

Execute `dotnet --version` in your repository root to identify the active SDK version, as implemented in [`plugins/dotnet-test/skills/platform-detection/SKILL.md`](https://github.com/dotnet/skills/blob/main/plugins/dotnet-test/skills/platform-detection/SKILL.md). If the output shows 8.x or 9.x, you must use the `--` separator for MTP arguments. If the output shows 10.x or higher, you can pass MTP arguments directly without the separator.

### Why do my MTP arguments work locally but fail in CI?

This typically occurs when the local environment runs .NET SDK 10+ while the CI pipeline uses SDK 8 or 9. The run-tests skill automatically detects this version mismatch, but manual scripts must account for the difference. Always verify CI agent SDK versions or use the version-agnostic patterns documented in [`plugins/dotnet-test/skills/run-tests/SKILL.md`](https://github.com/dotnet/skills/blob/main/plugins/dotnet-test/skills/run-tests/SKILL.md).

### Are VSTest-specific arguments affected by SDK version changes?

No. VSTest arguments are passed directly to the underlying `vstest.console` executable and do not require the `--` separator, regardless of whether you are using SDK 8, 9, or 10+. However, MTP-specific arguments (such as `--report-trx` or `--filter-trait`) must follow the SDK-dependent parsing rules outlined in the run-tests skill documentation.