Skip to content

Commit bfd57b0

Browse files
andravinclaude
andcommitted
feat(testing): expose pytest marks as tags in Test Explorer
Extract pytest marks (e.g., @pytest.mark.slow, @pytest.mark.integration) during test discovery and expose them as VS Code TestTags with IDs like "mark.slow", "mark.integration". This enables filtering tests by marks in the Test Explorer UI using @python-tests:mark.slow syntax. Changes: - Add tags field to TestItem TypedDict in pytest plugin - Extract marks from test_case.own_markers in create_test_node() - Add tags field to DiscoveredTestItem TypeScript type - Create TestTag objects from marks in populateTestTree() Fixes #20350 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 3c0301d commit bfd57b0

File tree

3 files changed

+15
-2
lines changed

3 files changed

+15
-2
lines changed

python_files/vscode_pytest/__init__.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ class TestItem(TestData):
5656

5757
lineno: str
5858
runID: str
59+
tags: list[str]
5960

6061

6162
class TestNode(TestData):
@@ -835,13 +836,22 @@ def create_test_node(
835836
str(test_case.location[1] + 1) if (test_case.location[1] is not None) else ""
836837
)
837838
absolute_test_id = get_absolute_test_id(test_case.nodeid, get_node_path(test_case))
839+
840+
# Extract pytest marks as tags
841+
tags: list[str] = []
842+
if hasattr(test_case, "own_markers"):
843+
for marker in test_case.own_markers:
844+
if marker.name and marker.name != "parametrize":
845+
tags.append(marker.name)
846+
838847
return {
839848
"name": test_case.name,
840849
"path": get_node_path(test_case),
841850
"lineno": test_case_loc,
842851
"type_": "test",
843852
"id_": absolute_test_id,
844853
"runID": absolute_test_id,
854+
"tags": tags,
845855
}
846856

847857

src/client/testing/testController/common/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ export type DiscoveredTestCommon = {
201201
export type DiscoveredTestItem = DiscoveredTestCommon & {
202202
lineno: number | string;
203203
runID: string;
204+
tags?: string[];
204205
};
205206

206207
export type DiscoveredTestNode = DiscoveredTestCommon & {

src/client/testing/testController/common/utils.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,10 @@ export function populateTestTree(
253253
// Create project-scoped vsId
254254
const vsId = projectId ? `${projectId}${PROJECT_ID_SEPARATOR}${child.id_}` : child.id_;
255255
const testItem = testController.createTestItem(vsId, child.name, Uri.file(child.path));
256-
testItem.tags = [RunTestTag, DebugTestTag];
256+
257+
// Create tags from pytest marks (if available) and combine with default tags
258+
const pytestMarkTags = (child.tags ?? []).map((tag) => ({ id: `mark.${tag}` }));
259+
testItem.tags = [RunTestTag, DebugTestTag, ...pytestMarkTags];
257260

258261
let range: Range | undefined;
259262
if (child.lineno) {
@@ -268,7 +271,6 @@ export function populateTestTree(
268271
}
269272
testItem.canResolveChildren = false;
270273
testItem.range = range;
271-
testItem.tags = [RunTestTag, DebugTestTag];
272274

273275
testRoot!.children.add(testItem);
274276
// add to our map - use runID as key, vsId as value

0 commit comments

Comments
 (0)