# Difference Between --filter, --filter-class, --filter-trait, and --filter-query in .NET Testing

> Master .NET testing filters: understand the difference between --filter, --filter-class, --filter-trait, and --filter-query to efficiently run your tests in xUnit v3.

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

---

**The `--filter` flag uses VSTest expression syntax for traditional frameworks, while `--filter-class`, `--filter-trait`, and `--filter-query` are xUnit v3-specific filters for the MTP runner that replace the generic expression with framework-specific filtering capabilities.**

When running tests with `dotnet test`, selecting specific test cases depends on your testing framework and SDK version. According to the `dotnet/skills` repository, these four flags serve distinct purposes across **VSTest**, **MSTest**, **NUnit**, **xUnit v2**, and the newer **xUnit v3** with the Multi-Targeted Projects (MTP) runner.

## Understanding the --filter Flag (VSTest Expression Syntax)

The `--filter` flag accepts generic test-selection expressions compatible with **VSTest**, **MSTest**, **NUnit**, and **xUnit v2**. In `dotnet/skills`, the `run-tests` skill documentation specifies that this flag supports expressions like `TestCategory=Integration` or compound queries such as `ClassName~MyTests&TestCategory!=Slow`.

However, **xUnit v3 does not support `--filter`** when running under the MTP runner. Attempting to use VSTest-style expressions like `--filter "ClassName=..."` with xUnit v3 will result in execution failure.

## Framework-Specific Filters for xUnit v3

When using **xUnit v3** with the MTP (Multi-Targeted Projects) runner introduced in .NET 9, you must use framework-specific filter flags instead of the generic `--filter` option.

### --filter-class for Class-Level Filtering

The `--filter-class` flag runs all tests in classes whose names match the supplied pattern. This filtering applies exclusively to xUnit v3 when using the MTP runner.

```bash
dotnet test --filter-class "*IntegrationTests*"

```

### --filter-trait for Trait-Based Filtering

The `--filter-trait` flag filters tests by specific trait key-value pairs, similar to the `[Trait("Category","Integration")]` attribute decoration in your test code.

```bash
dotnet test --filter-trait "Category=Integration"

```

### --filter-query for Combined Filtering

The `--filter-query` flag provides a path-segment query language that combines class-name and trait filtering in a single expression. This is the only flag that allows you to specify assembly, namespace, class, method, and optional trait qualifiers simultaneously using wildcards (`*`).

```bash
dotnet test -- --filter-query "/*/*/*IntegrationTests*/*[Category=Smoke]"

```

## SDK Version Syntax Requirements

The placement of these flags depends on your .NET SDK version. According to the source files in [`plugins/dotnet-test/skills/run-tests/SKILL.md`](https://github.com/dotnet/skills/blob/main/plugins/dotnet-test/skills/run-tests/SKILL.md), SDK 8 and 9 require a `--` separator to distinguish test runner flags from SDK flags:

```bash

# SDK 8/9 - requires separator

dotnet test -- --filter "TestCategory=Integration"
dotnet test -- --filter-query "/*/*/*Test*/*"

# SDK 10+ - separator optional

dotnet test --filter "TestCategory=Integration"

```

## Compatibility Reference

To select the correct filter flag, match your testing framework and runner:

- **VSTest/MSTest/NUnit/xUnit v2**: Use `--filter` with VSTest expression syntax
- **xUnit v3 on MTP**: Use `--filter-class`, `--filter-trait`, or `--filter-query` only
- **MTP with MSTest/NUnit**: Can use `--filter` (with `--` separator in SDK 8/9)

## Summary

- The `--filter` flag uses VSTest expression syntax and works with traditional frameworks but **fails with xUnit v3** on MTP.
- `--filter-class` filters xUnit v3 tests by class name patterns.
- `--filter-trait` filters xUnit v3 tests by specific trait key-value pairs.
- `--filter-query` combines class and trait filtering using a path-segment syntax for xUnit v3.
- SDK 8 and 9 require the `--` separator before these flags; SDK 10+ accepts them directly.

## Frequently Asked Questions

### Why does --filter fail with xUnit v3?

xUnit v3 uses the MTP (Multi-Targeted Projects) runner architecture, which does not implement the VSTest expression parser. According to the `dotnet/skills` filter-syntax documentation, xUnit v3 replaces the generic `--filter` with framework-specific alternatives (`--filter-class`, `--filter-trait`, `--filter-query`) that map directly to the xUnit v3 filtering API.

### What is the difference between --filter-trait and --filter?

While `--filter` can match traits using VSTest syntax (e.g., `TestCategory=Integration`), `--filter-trait` is specific to xUnit v3 on MTP and uses the exact trait key-value format without additional expression operators. The `--filter-trait` flag is more restrictive but provides precise control over xUnit v3 trait attributes.

### When should I use --filter-query instead of separate flags?

Use `--filter-query` when you need to combine multiple filtering dimensions—such as class name patterns and trait values—in a single expression. As documented in [`plugins/dotnet-test/skills/filter-syntax/SKILL.md`](https://github.com/dotnet/skills/blob/main/plugins/dotnet-test/skills/filter-syntax/SKILL.md), this is the only xUnit v3 filter that supports wildcards across assembly, namespace, class, and method segments while simultaneously qualifying by traits.

### Do I need the -- separator when using these flags?

For .NET SDK versions 8 and 9, you must place `--` before the filter flags when using the MTP runner to separate SDK arguments from test runner arguments. Starting with SDK 10, this separator is optional for all filter types.