Skip to content

Commit 629ca42

Browse files
authored
Support pytest parameterized tests spanning multiple classes when calling the same setup function (#23535)
fixes #23527
1 parent 838807d commit 629ca42

File tree

4 files changed

+144
-2
lines changed

4 files changed

+144
-2
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import pytest
2+
3+
4+
@pytest.fixture(scope="function", params=[1, 2])
5+
def setup(request):
6+
return request.param
7+
8+
9+
class TestClass1:
10+
def test_method1(self, setup): # test_marker--TestClass1::test_method1
11+
assert 1 == 1
12+
13+
14+
class TestClass2:
15+
def test_method1(self, setup): # test_marker--TestClass2::test_method1
16+
assert 2 == 2

python_files/tests/pytestadapter/expected_discovery_test_output.py

Lines changed: 122 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1273,4 +1273,125 @@
12731273
"id_": TEST_DATA_PATH_STR,
12741274
}
12751275

1276-
print(param_same_name_expected_output)
1276+
test_param_span_class_expected_output = {
1277+
"name": ".data",
1278+
"path": TEST_DATA_PATH_STR,
1279+
"type_": "folder",
1280+
"children": [
1281+
{
1282+
"name": "test_param_span_class.py",
1283+
"path": os.fspath(TEST_DATA_PATH / "test_param_span_class.py"),
1284+
"type_": "file",
1285+
"id_": os.fspath(TEST_DATA_PATH / "test_param_span_class.py"),
1286+
"children": [
1287+
{
1288+
"name": "TestClass1",
1289+
"path": os.fspath(TEST_DATA_PATH / "test_param_span_class.py"),
1290+
"type_": "class",
1291+
"children": [
1292+
{
1293+
"name": "test_method1",
1294+
"path": os.fspath(TEST_DATA_PATH / "test_param_span_class.py"),
1295+
"type_": "function",
1296+
"children": [
1297+
{
1298+
"name": "[1]",
1299+
"path": os.fspath(TEST_DATA_PATH / "test_param_span_class.py"),
1300+
"lineno": find_test_line_number(
1301+
"TestClass1::test_method1",
1302+
os.fspath(TEST_DATA_PATH / "test_param_span_class.py"),
1303+
),
1304+
"type_": "test",
1305+
"id_": get_absolute_test_id(
1306+
"test_param_span_class.py::TestClass1::test_method1[1]",
1307+
TEST_DATA_PATH / "test_param_span_class.py",
1308+
),
1309+
"runID": get_absolute_test_id(
1310+
"test_param_span_class.py::TestClass1::test_method1[1]",
1311+
TEST_DATA_PATH / "test_param_span_class.py",
1312+
),
1313+
},
1314+
{
1315+
"name": "[2]",
1316+
"path": os.fspath(TEST_DATA_PATH / "test_param_span_class.py"),
1317+
"lineno": find_test_line_number(
1318+
"TestClass1::test_method1",
1319+
os.fspath(TEST_DATA_PATH / "test_param_span_class.py"),
1320+
),
1321+
"type_": "test",
1322+
"id_": get_absolute_test_id(
1323+
"test_param_span_class.py::TestClass1::test_method1[2]",
1324+
TEST_DATA_PATH / "test_param_span_class.py",
1325+
),
1326+
"runID": get_absolute_test_id(
1327+
"test_param_span_class.py::TestClass1::test_method1[2]",
1328+
TEST_DATA_PATH / "test_param_span_class.py",
1329+
),
1330+
},
1331+
],
1332+
"id_": os.fspath(
1333+
TEST_DATA_PATH
1334+
/ "test_param_span_class.py::TestClass1::test_method1"
1335+
),
1336+
}
1337+
],
1338+
"id_": "test_param_span_class.py::TestClass1",
1339+
},
1340+
{
1341+
"name": "TestClass2",
1342+
"path": os.fspath(TEST_DATA_PATH / "test_param_span_class.py"),
1343+
"type_": "class",
1344+
"children": [
1345+
{
1346+
"name": "test_method1",
1347+
"path": os.fspath(TEST_DATA_PATH / "test_param_span_class.py"),
1348+
"type_": "function",
1349+
"children": [
1350+
{
1351+
"name": "[1]",
1352+
"path": os.fspath(TEST_DATA_PATH / "test_param_span_class.py"),
1353+
"lineno": find_test_line_number(
1354+
"TestClass2::test_method1",
1355+
os.fspath(TEST_DATA_PATH / "test_param_span_class.py"),
1356+
),
1357+
"type_": "test",
1358+
"id_": get_absolute_test_id(
1359+
"test_param_span_class.py::TestClass2::test_method1[1]",
1360+
TEST_DATA_PATH / "test_param_span_class.py",
1361+
),
1362+
"runID": get_absolute_test_id(
1363+
"test_param_span_class.py::TestClass2::test_method1[1]",
1364+
TEST_DATA_PATH / "test_param_span_class.py",
1365+
),
1366+
},
1367+
{
1368+
"name": "[2]",
1369+
"path": os.fspath(TEST_DATA_PATH / "test_param_span_class.py"),
1370+
"lineno": find_test_line_number(
1371+
"TestClass2::test_method1",
1372+
os.fspath(TEST_DATA_PATH / "test_param_span_class.py"),
1373+
),
1374+
"type_": "test",
1375+
"id_": get_absolute_test_id(
1376+
"test_param_span_class.py::TestClass2::test_method1[2]",
1377+
TEST_DATA_PATH / "test_param_span_class.py",
1378+
),
1379+
"runID": get_absolute_test_id(
1380+
"test_param_span_class.py::TestClass2::test_method1[2]",
1381+
TEST_DATA_PATH / "test_param_span_class.py",
1382+
),
1383+
},
1384+
],
1385+
"id_": os.fspath(
1386+
TEST_DATA_PATH
1387+
/ "test_param_span_class.py::TestClass2::test_method1"
1388+
),
1389+
}
1390+
],
1391+
"id_": "test_param_span_class.py::TestClass2",
1392+
},
1393+
],
1394+
}
1395+
],
1396+
"id_": TEST_DATA_PATH_STR,
1397+
}

python_files/tests/pytestadapter/test_discovery.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ def test_parameterized_error_collect():
109109
@pytest.mark.parametrize(
110110
"file, expected_const",
111111
[
112+
(
113+
"test_param_span_class.py",
114+
expected_discovery_test_output.test_param_span_class_expected_output,
115+
),
112116
(
113117
"test_multi_class_nest.py",
114118
expected_discovery_test_output.nested_classes_expected_test_output,

python_files/vscode_pytest/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,8 @@ def build_test_tree(session: pytest.Session) -> TestNode:
467467
function_name, get_node_path(test_case), parent_id
468468
)
469469
function_nodes_dict[parent_id] = function_test_node
470-
function_test_node["children"].append(test_node)
470+
if test_node not in function_test_node["children"]:
471+
function_test_node["children"].append(test_node)
471472
# Check if the parent node of the function is file, if so create/add to this file node.
472473
if isinstance(test_case.parent, pytest.File):
473474
try:

0 commit comments

Comments
 (0)