filter-syntax — Claude Code skill: what it does, how to install
A reference skill for .NET test filter syntax across VSTest and MTP. Helps agents format and convert filter arguments for MSTest, NUnit, xUnit v3, and TUnit.
npx skills add dotnet/skills --skill filter-syntax -a claude-codeWhat filter-syntax does
This reference skill provides the exact filtering syntax for .NET testing across VSTest and Microsoft Testing Platform (MTP). It details operators, combinators, and properties for MSTest, NUnit, xUnit, and TUnit, including migration patterns from VSTest expressions to MTP flags.
For VSTest and compatible runners, the guide specifies --filter expressions using property operators like exact matches and substrings. On MTP, it defines runner-specific differences: dedicated --filter-class or --filter-query arguments for xUnit v3, alongside tree-path syntax with --treenode-filter for TUnit.
Because the skill sets user-invocable: false and disable-model-invocation: true, users do not call it directly. Consuming skills like run-tests or mtp-hot-reload pull in this reference only after detecting the test framework.
What it helps with
- construct --filter expressions for MSTest and NUnit runs
- convert VSTest filter strings into xUnit v3 MTP command flags
- format --treenode-filter paths with wildcards for TUnit
- build complex --filter-query expressions for xUnit.net v3
Example prompts for the agent
- Run only the integration tests in LoginTests using dotnet test
- Translate this VSTest filter FullyQualifiedName~Orders to xUnit v3 on MTP
- Generate a TUnit test execution command filtered by Priority=Critical
How to install filter-syntax
1Skills CLI (Vercel)
npx skills add dotnet/skills --skill filter-syntax -a claude-code2Manually: put the files in place
~/.claude/skills/filter-syntax/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/filter-syntax/
1Skills CLI (Vercel)
npx skills add dotnet/skills --skill filter-syntax -a codex2Manually: put the files in place
.agents/skills/filter-syntax/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add dotnet/skills --skill filter-syntax -a cursor2Manually: put the files in place
.cursor/skills/filter-syntax/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install dotnet/skills filter-syntax2Manually: put the files in place
.github/skills/filter-syntax/SKILL.md1Skills CLI (Vercel)
npx skills add dotnet/skills --skill filter-syntax -a gemini-cli2Platform CLI
gemini skills install https://github.com/dotnet/skills --path plugins/dotnet-test/skills/filter-syntaxManually: put the files in place
.devin/skills/filter-syntax/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add dotnet/skills --skill filter-syntax -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about filter-syntax
How to install filter-syntax in Claude Code?
Run npx skills add dotnet/skills --skill filter-syntax -a claude-code. The file will be placed in ~/.claude/skills/filter-syntax/SKILL.md.
What does the filter-syntax skill do?
It acts as a syntax reference for filtering .NET tests. It guides the assistant in selecting proper flags and operators for VSTest, MTP, MSTest, NUnit, xUnit v3, and TUnit.
Can you call this skill directly?
No, its configuration specifies user-invocable: false. It is designed to be loaded by workflow skills such as run-tests and mtp-hot-reload once the test framework is known.
Source text
SKILL.md · MIT
--- name: filter-syntax description: "Reference-only filter syntax for VSTest and MTP with MSTest, NUnit, xUnit v3, and TUnit. Load only after the platform/framework is known and a consumer needs to create or translate a filter. Do not load for unfiltered runs or platform detection. Used by run-tests and mtp-hot-reload; never invoke directly." user-invocable: false disable-model-invocation: true license: MIT --- # Test Filter Syntax Reference Filter syntax depends on the **platform** and **test framework**. ## VSTest filters (MSTest, xUnit v2, NUnit on VSTest) ```bash dotnet test --filter <EXPRESSION> ``` Expression syntax: `<Property><Operator><Value>[|&<Expression>]` **Operators:** | Operator | Meaning | |----------|---------| | `=` | Exact match | | `!=` | Not exact match | | `~` | Contains | | `!~` | Does not contain | **Combinators:** `|` (OR), `&` (AND). Parentheses for grouping: `(A|B)&C` **Supported properties by framework:** | Framework | Properties | |-----------|-----------| | MSTest | `FullyQualifiedName`, `Name`, `ClassName`, `Priority`, `TestCategory` | | xUnit | `FullyQualifiedName`, `DisplayName`, `Traits` | | NUnit | `FullyQualifiedName`, `Name`, `Priority`, `TestCategory` | An expression without an operator is treated as `FullyQualifiedName~<value>`. **Examples (VSTest):** ```bash # Run tests whose name contains "LoginTest" dotnet test --filter "Name~LoginTest" # Run a specific test class dotnet test --filter "ClassName=MyNamespace.MyTestClass" # Run tests in a category dotnet test --filter "TestCategory=Integration" # Exclude a category dotnet test --filter "TestCategory!=Slow" # Combine: class AND category dotnet test --filter "ClassName=MyNamespace.MyTestClass&TestCategory=Unit" # Either of two classes dotnet test --filter "ClassName=MyNamespace.ClassA|ClassName=MyNamespace.ClassB" ``` ## MTP filters — MSTest and NUnit MSTest and NUnit on MTP use the **same `--filter` syntax** as VSTest (same properties, operators, and combinators). The only difference is how the flag is passed: ```bash # .NET SDK 8/9 (after --) dotnet test -- --filter "Name~LoginTest" # .NET SDK 10+ (direct) dotnet test --filter "Name~LoginTest" ``` ## MTP filters — xUnit (v3) xUnit v3 on MTP uses **framework-specific filter flags** instead of the generic `--filter` expression: | Flag | Description | |------|-------------| | `--filter-class "name"` | Run all tests in a given class | | `--filter-not-class "name"` | Exclude all tests in a given class | | `--filter-method "name"` | Run a specific test method | | `--filter-not-method "name"` | Exclude a specific test method | | `--filter-namespace "name"` | Run all tests in a namespace | | `--filter-not-namespace "name"` | Exclude all tests in a namespace | | `--filter-trait "name=value"` | Run tests with a matching trait | | `--filter-not-trait "name=value"` | Exclude tests with a matching trait | Multiple values can be specified with a single flag: `--filter-class Foo Bar`. ```bash # .NET SDK 8/9 dotnet test -- --filter-class "MyNamespace.LoginTests" # .NET SDK 10+ dotnet test --filter-class "MyNamespace.LoginTests" # Combine: namespace + trait dotnet test --filter-namespace "MyApp.Tests.Integration" --filter-trait "Category=Smoke" ``` ### xUnit v3 query filter language For complex expressions, use `--filter-query` with a path-segment syntax: ```text /<assemblyFilter>/<namespaceFilter>/<classFilter>/<methodFilter>[traitName=traitValue] ``` Each segment matches against: assembly name, namespace, class name, method name. Use `*` for "match all" in any segment. Documentation: <https://xunit.net/docs/query-filter-language> ```shell # xUnit.net v3 MTP — using query language (assembly/namespace/class/method[trait]) dotnet test -- --filter-query "/*/*/*IntegrationTests*/*[Category=Smoke]" ``` ## MTP filters — TUnit TUnit uses `--treenode-filter` with a path-based syntax: ```text --treenode-filter "/<Assembly>/<Namespace>/<ClassName>/<TestName>" ``` Wildcards (`*`) are supported in any segment. Filter operators can be appended to test names for property-based filtering. | Operator | Meaning | |----------|---------| | `*` | Wildcard match | | `=` | Exact property match (e.g., `[Category=Unit]`) | | `!=` | Exclude property value | | `&` | AND (combine conditions) | | `\|` | OR (within a segment, requires parentheses) | **Examples (TUnit):** ```bash # All tests in a class dotnet run --treenode-filter "/*/*/LoginTests/*" # A specific test dotnet run --treenode-filter "/*/*/*/AcceptCookiesTest" # By namespace prefix (wildcard) dotnet run --treenode-filter "/*/MyProject.Tests.Api*/*/*" # By custom property dotnet run --treenode-filter "/*/*/*/*[Category=Smoke]" # Exclude by property dotnet run --treenode-filter "/*/*/*/*[Category!=Slow]" # OR across classes dotnet run --treenode-filter "/*/*/(LoginTests)|(SignupTests)/*" # Combined: namespace + property dotnet run --treenode-filter "/*/MyProject.Tests.Integration/*/*/*[Priority=Critical]" ``` ## VSTest → MTP filter translation (for migration) **MSTest, NUnit, and xUnit.net v2 (with `YTest.MTP.XUnit2`)**: The VSTest `--filter` syntax is identical on both VSTest and MTP. No changes needed. **xUnit.net v3 (native MTP)**: xUnit.net v3 does NOT support the VSTest `--filter` syntax on MTP. Translate filters using xUnit.net v3's native options: | VSTest `--filter` syntax | xUnit.net v3 MTP equivalent | Notes | |---|---|---| | `FullyQualifiedName~ClassName` | `--filter-class *ClassName*` | Wildcards required for substring match | | `FullyQualifiedName=Ns.Class.Method` | `--filter-method Ns.Class.Method` | Exact match on fully qualified method | | `Name=MethodName` | `--filter-method *MethodName*` | Wildcards for substring match | | `Category=Value` (trait) | `--filter-trait "Category=Value"` | Filter by trait name/value pair | | Complex expressions | `--filter-query "expr"` | Uses xUnit.net query filter language (see above) |
© dotnet · MIT · dotnet/skills