Skip to content

Commit 27df831

Browse files
committed
Improve test filter generation skill.
1 parent 6c1fe2c commit 27df831

2 files changed

Lines changed: 104 additions & 46 deletions

File tree

.github/prompts/minimize-test-overlap.prompt.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,19 @@ Your task is to analyze the user's test suite using the `AnalyzeTestOverlap.ps1`
1010

1111
## Skills
1212
This prompt leverages the following skills for specific sub-tasks:
13-
- [generate-mstest-filter](.github/skills/generate-mstest-filter/SKILL.md) - For generating well-formed MSTest filter expressions
13+
- [generate-mstest-filter](../skills/generate-mstest-filter/SKILL.md) - For generating well-formed MSTest filter expressions
1414

1515
## Tools
16-
You have access to the analysis script at `[AnalyzeTestOverlap.ps1](.\prompts\scripts\AnalyzeTestOverlap.ps1)`.
16+
You have access to the analysis script at `[AnalyzeTestOverlap.ps1](./scripts/AnalyzeTestOverlap.ps1)`.
1717

1818
## Workflow
1919
1. **Parse or Generate Test Filter**:
2020
* If `${input:filter}` is a valid MSTest filter expression (e.g., `FullyQualifiedName~MyTests`), use it directly.
21-
* If `${input:filter}` is a loose description (e.g., "connection tests" or "SqlCommand class"), follow the instructions in the [generate-mstest-filter](.github/skills/generate-mstest-filter/SKILL.md) skill to generate a proper filter expression.
21+
* If `${input:filter}` is a loose description (e.g., "connection tests" or "SqlCommand class"), follow the instructions in the [generate-mstest-filter](../skills/generate-mstest-filter/SKILL.md) skill to generate a proper filter expression.
2222
* If `${input:filter}` is empty, ask the user for a test filter or description to target specific tests.
2323

2424
2. **Run Analysis**:
25-
* Run the script using the filter: `.\prompts\scripts\AnalyzeTestOverlap.ps1 -Filter "<filter>"`.
25+
* Run the script using the filter: `.\scripts\AnalyzeTestOverlap.ps1 -Filter "<filter>"`.
2626
* *Note*: The script produces a console summary and a `test-coverage-analysis.json` file.
2727

2828
3. **Review Overlap**:

.github/skills/generate-mstest-filter/SKILL.md

Lines changed: 100 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,16 @@ This skill generates MSTest filter expressions for use with `dotnet test --filte
1717

1818
### Supported Properties
1919

20-
| Property | Description |
21-
|----------|-------------|
22-
| `FullyQualifiedName` | Full namespace + class + method name (e.g., `Namespace.Class.Method`) |
23-
| `Name` | Test method name only |
24-
| `ClassName` | Full namespace + class name (must include namespace) |
25-
| `Priority` | Priority attribute value (integer) |
26-
| `TestCategory` | TestCategory attribute value (string) |
20+
| Property | Description | Supported By |
21+
|----------|-------------|--------------|
22+
| `FullyQualifiedName` | Full namespace + class + method name (e.g., `Namespace.Class.Method`) | MSTest, xUnit, NUnit |
23+
| `DisplayName` | The display name of the test (often same as FullyQualifiedName for xUnit) | MSTest, xUnit, NUnit |
24+
| `Name` | Test method name only | MSTest only (not xUnit) |
25+
| `ClassName` | Full namespace + class name (must include namespace) | MSTest only (not xUnit) |
26+
| `Priority` | Priority attribute value (integer) | MSTest (with `[Priority]` attribute) |
27+
| `TestCategory` | TestCategory attribute value (string) | MSTest (with `[TestCategory]` attribute) |
28+
29+
> **Important**: For xUnit tests (common in .NET Core projects), **always use `FullyQualifiedName` or `DisplayName`**. The `Name` and `ClassName` properties are not populated by xUnit and will result in no matches.
2730
2831
### Operators
2932

@@ -38,41 +41,47 @@ This skill generates MSTest filter expressions for use with `dotnet test --filte
3841

3942
| Operator | Meaning | Example |
4043
|----------|---------|---------|
41-
| `\|` | OR | `Name~Test1\|Name~Test2` |
42-
| `&` | AND | `ClassName~MyClass&Priority=1` |
43-
| `()` | Grouping | `(Name~Test1\|Name~Test2)&Priority=1` |
44+
| `\|` | OR | `FullyQualifiedName~Test1\|FullyQualifiedName~Test2` |
45+
| `&` | AND | `FullyQualifiedName~MyClass&Priority=1` |
46+
| `()` | Grouping | `(FullyQualifiedName~Test1\|FullyQualifiedName~Test2)&Priority=1` |
4447

4548
## Instructions
4649

4750
1. **Analyze the user's description** to identify:
4851
- Test names, patterns, or keywords mentioned
49-
- Class names or namespaces referenced
52+
- Class names or namespaces referenced
5053
- Categories or priorities specified
5154
- Whether tests should be included or excluded
52-
53-
2. **Choose the appropriate property**:
54-
- Use `FullyQualifiedName` for namespace + class + method patterns
55-
- Use `Name` for just the method name
56-
- Use `ClassName` for filtering by test class (always include namespace)
57-
- Use `TestCategory` for category-based filtering
58-
- Use `Priority` for priority-based filtering
59-
60-
3. **Select the correct operator**:
61-
- Use `~` (contains) for partial matches and patterns
62-
- Use `=` for exact matches
55+
- Whether the user referenced a **file name** (look for `.cs` extension or file path patterns)
56+
57+
2. **Handle file name inputs**:
58+
- If the user provides a file name (e.g., `ChannelDbConnectionPoolTest.cs`), extract the class name by removing the `.cs` extension
59+
- File names typically correspond to the test class name (e.g., `SqlConnectionTest.cs` → class `SqlConnectionTest`)
60+
- Use `FullyQualifiedName~ClassName` pattern for file-based inputs
61+
62+
3. **Choose the appropriate property**:
63+
- **For xUnit tests (most .NET Core projects)**: Always use `FullyQualifiedName` or `DisplayName`
64+
- **For MSTest only**: `Name` and `ClassName` properties are also available
65+
- Use `FullyQualifiedName~` with contains operator for maximum compatibility
66+
- Use `TestCategory` for category-based filtering (MSTest only)
67+
- Use `Priority` for priority-based filtering (MSTest only)
68+
69+
4. **Select the correct operator**:
70+
- Use `~` (contains) for partial matches and patterns - **this is the safest default**
71+
- Use `=` for exact matches only when you know the full value
6372
- Use `!=` or `!~` for exclusions
6473

65-
4. **Combine conditions** as needed:
74+
5. **Combine conditions** as needed:
6675
- Use `|` (OR) when any condition should match
6776
- Use `&` (AND) when all conditions must match
6877
- Use parentheses `()` for complex logic
6978

70-
5. **Format the output** as a complete `dotnet test` command:
79+
6. **Format the output** as a complete `dotnet test` command:
7180
```
7281
dotnet test --filter "<expression>"
7382
```
7483

75-
6. **Handle special characters**:
84+
7. **Handle special characters**:
7685
- Escape `!` with `\!` on Linux/macOS shells
7786
- Use `%2C` for commas in generic type parameters
7887
- URL-encode special characters in Name/DisplayName values
@@ -85,78 +94,118 @@ This skill generates MSTest filter expressions for use with `dotnet test --filte
8594
dotnet test --filter "FullyQualifiedName~Connection"
8695
```
8796

88-
### Example 2: Run tests in a specific class
97+
### Example 2: Run tests in a specific class (xUnit compatible)
8998
**User says**: "Run tests in SqlConnectionTest class"
9099
```bash
91-
dotnet test --filter "ClassName=Microsoft.Data.SqlClient.Tests.SqlConnectionTest"
100+
dotnet test --filter "FullyQualifiedName~SqlConnectionTest"
92101
```
93-
Note: If the full namespace is unknown, use contains:
102+
> **Note**: Avoid using `ClassName=` for xUnit tests - it won't work. Always use `FullyQualifiedName~` for cross-framework compatibility.
103+
104+
### Example 3: Run tests from a specific file
105+
**User says**: "Run tests in ChannelDbConnectionPoolTest.cs"
94106
```bash
95-
dotnet test --filter "ClassName~SqlConnectionTest"
107+
dotnet test --filter "FullyQualifiedName~ChannelDbConnectionPoolTest"
96108
```
109+
> Strip the `.cs` extension and use `FullyQualifiedName~` with the class name.
97110
98-
### Example 3: Run a specific test method
111+
### Example 4: Run a specific test method
99112
**User says**: "Run the TestOpenConnection test"
100113
```bash
101-
dotnet test --filter "Name=TestOpenConnection"
114+
dotnet test --filter "FullyQualifiedName~TestOpenConnection"
102115
```
116+
> Use `FullyQualifiedName~` instead of `Name=` for xUnit compatibility.
103117
104-
### Example 4: Run tests by category
118+
### Example 5: Run tests by category (MSTest only)
105119
**User says**: "Run all tests in CategoryA"
106120
```bash
107121
dotnet test --filter "TestCategory=CategoryA"
108122
```
109123

110-
### Example 5: Run high priority tests
124+
### Example 6: Run high priority tests (MSTest only)
111125
**User says**: "Run priority 1 tests"
112126
```bash
113127
dotnet test --filter "Priority=1"
114128
```
115129

116-
### Example 6: Combine multiple conditions (AND)
130+
### Example 7: Combine multiple conditions (AND)
117131
**User says**: "Run connection tests that are priority 1"
118132
```bash
119133
dotnet test --filter "FullyQualifiedName~Connection&Priority=1"
120134
```
121135

122-
### Example 7: Combine multiple conditions (OR)
136+
### Example 8: Combine multiple conditions (OR)
123137
**User says**: "Run tests for SqlConnection or SqlCommand"
124138
```bash
125139
dotnet test --filter "FullyQualifiedName~SqlConnection|FullyQualifiedName~SqlCommand"
126140
```
127141

128-
### Example 8: Exclude tests
142+
### Example 9: Exclude tests
129143
**User says**: "Run all tests except integration tests"
130144
```bash
131145
dotnet test --filter "FullyQualifiedName!~Integration"
132146
```
133147

134-
### Example 9: Complex filter with grouping
148+
### Example 10: Complex filter with grouping
135149
**User says**: "Run connection or command tests that are in CategoryA"
136150
```bash
137151
dotnet test --filter "(FullyQualifiedName~Connection|FullyQualifiedName~Command)&TestCategory=CategoryA"
138152
```
139153

140-
### Example 10: Exclude specific test method
154+
### Example 11: Exclude specific test method
141155
**User says**: "Run all tests except TestSlowOperation"
142156
```bash
143-
dotnet test --filter "Name!=TestSlowOperation"
157+
dotnet test --filter "FullyQualifiedName!~TestSlowOperation"
144158
```
145159

146-
### Example 11: Multiple exclusions
160+
### Example 12: Multiple exclusions
147161
**User says**: "Run tests but skip integration and performance tests"
148162
```bash
149163
dotnet test --filter "FullyQualifiedName!~Integration&FullyQualifiedName!~Performance"
150164
```
151165

166+
## Verification (Required)
167+
168+
**Always verify the generated filter before presenting it to the user.** Use the `--list-tests` flag to confirm the filter matches the expected tests:
169+
170+
```bash
171+
dotnet test <project.csproj> --list-tests --filter "<your-filter>" --framework <target-framework>
172+
```
173+
174+
### Verification Steps
175+
176+
1. **Run the list-tests command** with the generated filter
177+
2. **Check the output**:
178+
- If tests are listed → filter is valid
179+
- If "No test matches the given testcase filter" → filter is invalid, needs adjustment
180+
3. **If no matches**, try these fixes in order:
181+
- Switch from `ClassName=` or `Name=` to `FullyQualifiedName~`
182+
- Remove the namespace prefix and use just the class/method name with `~`
183+
- Try `DisplayName~` as an alternative
184+
4. **Re-run verification** after any changes
185+
186+
### Example Verification
187+
188+
```bash
189+
# Generate filter for "ChannelDbConnectionPoolTest" class
190+
dotnet test tests/UnitTests/UnitTests.csproj --list-tests --filter "FullyQualifiedName~ChannelDbConnectionPoolTest" --framework net9.0
191+
192+
# Expected output shows matching tests:
193+
# The following Tests are available:
194+
# Microsoft.Data.SqlClient.UnitTests.ConnectionPool.ChannelDbConnectionPoolTest.GetConnectionEmptyPool_ShouldCreateNewConnection(...)
195+
# ...
196+
```
197+
152198
## Error Handling
153199

154200
- If the user's description is ambiguous, ask for clarification about:
155201
- Whether they want exact match or contains
156202
- The full class name or namespace if needed
157203
- Whether conditions should be AND or OR
158204

159-
- If ClassName filter doesn't work, remind the user that `ClassName` must include the namespace (e.g., `Namespace.ClassName`, not just `ClassName`)
205+
- **If a filter returns no matches**:
206+
- First, verify the test class/method exists in the project
207+
- Switch to `FullyQualifiedName~` with contains operator
208+
- Check if the project uses xUnit (common in .NET Core) - if so, avoid `Name` and `ClassName` properties
160209

161210
- For complex filters, validate that parentheses are balanced
162211

@@ -171,5 +220,14 @@ dotnet test --filter "FullyQualifiedName!~Integration&FullyQualifiedName!~Perfor
171220

172221
- For project-specific tests, add the project path:
173222
```bash
174-
dotnet test path/to/project.csproj --filter "Name~MyTest"
223+
dotnet test path/to/project.csproj --filter "FullyQualifiedName~MyTest"
175224
```
225+
226+
## Common Pitfalls
227+
228+
| Problem | Cause | Solution |
229+
|---------|-------|----------|
230+
| No test matches filter | Using `Name=` or `ClassName=` with xUnit | Use `FullyQualifiedName~` instead |
231+
| No test matches filter | Using just class name without namespace in `ClassName=` | Use `FullyQualifiedName~ClassName` |
232+
| Filter matches too many tests | Using overly broad `~` pattern | Add more specific qualifiers or use `&` with additional conditions |
233+
| TestCategory filter doesn't work | Project uses xUnit, which doesn't support TestCategory | Use `[Trait]` attributes with xUnit and filter by trait name |

0 commit comments

Comments
 (0)