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

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.

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.

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 (*).

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, SDK 8 and 9 require a -- separator to distinguish test runner flags from SDK flags:


# 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, 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →