fix(testing): respect TestRunRequest.exclude when running tests#25743
Open
andravin wants to merge 5 commits into
Open
fix(testing): respect TestRunRequest.exclude when running tests#25743andravin wants to merge 5 commits into
andravin wants to merge 5 commits into
Conversation
andravin
force-pushed
the
fix/test-explorer-exclude-filtering
branch
2 times, most recently
from
February 3, 2026 04:17
36418f2 to
fc38e1b
Compare
Author
|
Tested against main. Unit tests have been added. |
andravin
added a commit
to andravin/vscode-python
that referenced
this pull request
Feb 14, 2026
The VS Code Test Explorer API specifies that TestRunRequest.exclude contains tests the user has marked as excluded (e.g., via filtering). Per the API contract, "exclusions should apply after inclusions." Previously, the Python extension ignored request.exclude entirely, causing "Run Tests" to run all tests even when the user had filtered the Test Explorer view. This fix adds exclude handling at two levels: 1. In getTestItemsForWorkspace(): Filter out excluded items before passing to the test adapter (checks ancestors for top-level items) 2. In WorkspaceTestAdapter.executeTests(): Pre-expand the exclude set to include all descendants, then pass to getTestCaseNodes() which skips excluded nodes with O(1) set lookups during traversal Also adds a visited set to getTestCaseNodes() to avoid expanding the same node multiple times when includes contains overlapping items. Fixes the issue where filtering tests in Test Explorer (e.g., by tag) and clicking "Run Tests" would still run all tests. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The getTestCaseNodes function was changed from a single-parameter function returning an array to a 4-parameter function that mutates the collection array in place (with additional visited and excludeSet parameters for exclude support). Updated the test stub accordingly. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add unit tests for isTestItemExcluded, expandExcludeSet, and getTestCaseNodes with exclude/visited parameters. Verifies ancestor chain checking, descendant expansion, and correct node skipping. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…kspace Remove isTestItemExcluded and exclusion logic from getTestItemsForWorkspace since exclusions are fully handled downstream via expandExcludeSet and getTestCaseNodes in WorkspaceTestAdapter.executeTests. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…cution The new project-based test execution path (executeTestsForProjects) was not respecting TestRunRequest.exclude. This adds exclude filtering by: - Importing expandExcludeSet and getTestCaseNodes from testItemUtilities - Creating expanded exclude set from request.exclude in executeTestsForProjects - Using getTestCaseNodes (with exclude support) instead of getTestCaseNodesRecursive Also fixes testMocks.ts to create realistic mock TestItems: - Set canResolveChildren=true when children are present - Include RunTestTag and DebugTestTag (required for getTestCaseNodes) Adds tests for exclude filtering in project-based execution including multi-project scenarios. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
andravin
force-pushed
the
fix/test-explorer-exclude-filtering
branch
from
February 18, 2026 06:34
2e818df to
29561ad
Compare
There was a problem hiding this comment.
Pull request overview
This PR updates the Python extension’s VS Code Test Explorer execution path to honor TestRunRequest.exclude, ensuring tests filtered/excluded by the UI are not executed (including their descendants), aligning behavior with the VS Code Testing API contract.
Changes:
- Pass
request.excludeintoWorkspaceTestAdapter.executeTests()and filter excluded nodes during include expansion. - Add
expandExcludeSet()+ visited-node tracking ingetTestCaseNodes()to support O(1) exclusion checks and avoid repeated traversal for overlapping includes. - Add/adjust unit tests and mocks to cover exclude handling for both single-workspace and project-based execution.
Show a summary per file
| File | Description |
|---|---|
| src/client/testing/testController/controller.ts | Plumbs request.exclude through to the workspace test adapter execution call. |
| src/client/testing/testController/workspaceTestAdapter.ts | Expands/filters excluded items when collecting leaf test cases for execution. |
| src/client/testing/testController/common/testItemUtilities.ts | Adds expandExcludeSet() and extends getTestCaseNodes() with visited/exclude support. |
| src/client/testing/testController/common/projectTestExecution.ts | Applies exclude handling in project-based execution by filtering leaf expansion. |
| src/test/testing/testController/workspaceTestAdapter.unit.test.ts | Updates stubbing of getTestCaseNodes() to match new signature/behavior. |
| src/test/testing/testController/testMocks.ts | Improves test item mocks (tags + canResolveChildren) to better match real test tree behavior. |
| src/test/testing/testController/testItemUtilities.unit.test.ts | Adds focused unit coverage for exclude expansion and visited/exclude traversal behavior. |
| src/test/testing/testController/common/projectTestExecution.unit.test.ts | Adds coverage to ensure exclude items are not executed in project-based execution (including multi-project). |
Review details
- Files reviewed: 8/8 changed files
- Comments generated: 2
- Review effort level: Low
Comment on lines
62
to
80
| const testCaseNodes: TestItem[] = []; | ||
| const testCaseIdsSet = new Set<string>(); | ||
| const visitedNodes = new Set<TestItem>(); | ||
| const rawExcludeSet = excludes?.length ? new Set(excludes) : undefined; | ||
| const excludeSet = expandExcludeSet(rawExcludeSet); | ||
| const testCaseIds: string[] = []; | ||
| try { | ||
| // first fetch all the individual test Items that we necessarily want | ||
| // Expand included items to leaf test nodes. | ||
| // getTestCaseNodes handles visited tracking and exclusion filtering. | ||
| includes.forEach((t) => { | ||
| const nodes = getTestCaseNodes(t); | ||
| testCaseNodes.push(...nodes); | ||
| getTestCaseNodes(t, testCaseNodes, visitedNodes, excludeSet); | ||
| }); | ||
| // iterate through testItems nodes and fetch their unittest runID to pass in as argument | ||
| // Collect runIDs for the test nodes to execute. | ||
| testCaseNodes.forEach((node) => { | ||
| runInstance.started(node); // do the vscode ui test item start here before runtest | ||
| runInstance.started(node); | ||
| const runId = this.resultResolver.vsIdToRunId.get(node.id); | ||
| if (runId) { | ||
| testCaseIdsSet.add(runId); | ||
| testCaseIds.push(runId); | ||
| } | ||
| }); |
Comment on lines
+235
to
244
| // Mark items as started and collect test IDs | ||
| const testCaseIds: string[] = []; | ||
| for (const node of testCaseNodes) { | ||
| runInstance.started(node); | ||
| const runId = project.resultResolver.vsIdToRunId.get(node.id); | ||
| if (runId) { | ||
| testCaseIds.push(runId); | ||
| } | ||
| } | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The VS Code Test Explorer API documents that
TestRunRequest.excludecontains tests the user has marked as excluded (e.g., via filtering). The documentation says,Previously, the Python extension ignored
request.exclude, so invoking Run Tests would execute all tests even when the Test Explorer view was filtered.This fix adds exclude handling in
WorkspaceTestAdapter.executeTests(): Pre-expand the exclude set to include all descendants, then pass togetTestCaseNodes()which skips excluded nodes with O(1) set lookups during traversalThis change also adds a visited set to
getTestCaseNodes()to avoid expanding the same node multiple times whenincludecontains overlapping items.Fixes the issue where filtering tests in Test Explorer (e.g., by tag) and clicking Run Tests would still run all tests.
Fixes #25742