Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix duplicate class names processed as single node in build test tree pytest #21601

Merged
merged 3 commits into from
Jul 10, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,11 @@ def test_add_positive_numbers(self): # test_marker--test_add_positive_numbers
def test_add_negative_numbers(self): # test_marker--test_add_negative_numbers
result = add(-2, -3)
self.assertEqual(result, -5)


class TestDuplicateFunction(unittest.TestCase):
# This test's id is unittest_folder/test_subtract.py::TestDuplicateFunction::test_dup_a. It has the same class name as
# another test, but it's in a different file, so it should not be confused.
# This test passes.
def test_dup_a(self): # test_marker--test_dup_a
self.assertEqual(1, 1)
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,11 @@ def test_subtract_negative_numbers( # test_marker--test_subtract_negative_numbe
result = subtract(-2, -3)
# This is intentional to test assertion failures
self.assertEqual(result, 100000)


class TestDuplicateFunction(unittest.TestCase):
# This test's id is unittest_folder/test_subtract.py::TestDuplicateFunction::test_dup_s. It has the same class name as
# another test, but it's in a different file, so it should not be confused.
# This test passes.
def test_dup_s(self): # test_marker--test_dup_s
self.assertEqual(1, 1)
47 changes: 45 additions & 2 deletions pythonFiles/tests/pytestadapter/expected_discovery_test_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,14 @@
# │ └── TestAddFunction
# │ ├── test_add_negative_numbers
# │ └── test_add_positive_numbers
# │ └── TestDuplicateFunction
# │ └── test_dup_a
# └── test_subtract.py
# └── TestSubtractFunction
# ├── test_subtract_negative_numbers
# └── test_subtract_positive_numbers
# │ └── TestDuplicateFunction
# │ └── test_dup_s
unittest_folder_path = os.fspath(TEST_DATA_PATH / "unittest_folder")
test_add_path = os.fspath(TEST_DATA_PATH / "unittest_folder" / "test_add.py")
test_subtract_path = os.fspath(TEST_DATA_PATH / "unittest_folder" / "test_subtract.py")
Expand Down Expand Up @@ -159,7 +163,26 @@
},
],
"id_": "unittest_folder/test_add.py::TestAddFunction",
}
},
{
"name": "TestDuplicateFunction",
"path": test_add_path,
"type_": "class",
"children": [
{
"name": "test_dup_a",
"path": test_add_path,
"lineno": find_test_line_number(
"test_dup_a",
test_add_path,
),
"type_": "test",
"id_": "unittest_folder/test_add.py::TestDuplicateFunction::test_dup_a",
"runID": "unittest_folder/test_add.py::TestDuplicateFunction::test_dup_a",
},
],
"id_": "unittest_folder/test_add.py::TestDuplicateFunction",
},
],
},
{
Expand Down Expand Up @@ -197,7 +220,26 @@
},
],
"id_": "unittest_folder/test_subtract.py::TestSubtractFunction",
}
},
{
"name": "TestDuplicateFunction",
"path": test_subtract_path,
"type_": "class",
"children": [
{
"name": "test_dup_s",
"path": test_subtract_path,
"lineno": find_test_line_number(
"test_dup_s",
test_subtract_path,
),
"type_": "test",
"id_": "unittest_folder/test_subtract.py::TestDuplicateFunction::test_dup_s",
"runID": "unittest_folder/test_subtract.py::TestDuplicateFunction::test_dup_s",
},
],
"id_": "unittest_folder/test_subtract.py::TestDuplicateFunction",
},
],
},
],
Expand All @@ -206,6 +248,7 @@
"id_": TEST_DATA_PATH_STR,
}


# This is the expected output for the dual_level_nested_folder tests
# └── dual_level_nested_folder
# └── test_top_folder.py
Expand Down
185 changes: 92 additions & 93 deletions pythonFiles/tests/pytestadapter/test_discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,104 +9,103 @@
from . import expected_discovery_test_output
from .helpers import TEST_DATA_PATH, runner


def test_import_error(tmp_path):
"""Test pytest discovery on a file that has a pytest marker but does not import pytest.

Copies the contents of a .txt file to a .py file in the temporary directory
to then run pytest discovery on.

The json should still be returned but the errors list should be present.

Keyword arguments:
tmp_path -- pytest fixture that creates a temporary directory.
"""
# Saving some files as .txt to avoid that file displaying a syntax error for
# the extension as a whole. Instead, rename it before running this test
# in order to test the error handling.
file_path = TEST_DATA_PATH / "error_pytest_import.txt"
temp_dir = tmp_path / "temp_data"
temp_dir.mkdir()
p = temp_dir / "error_pytest_import.py"
shutil.copyfile(file_path, p)
actual_list: Optional[List[Dict[str, Any]]] = runner(
["--collect-only", os.fspath(p)]
)
assert actual_list
for actual in actual_list:
assert all(item in actual for item in ("status", "cwd", "error"))
assert actual["status"] == "error"
assert actual["cwd"] == os.fspath(TEST_DATA_PATH)
assert len(actual["error"]) == 2


def test_syntax_error(tmp_path):
"""Test pytest discovery on a file that has a syntax error.

Copies the contents of a .txt file to a .py file in the temporary directory
to then run pytest discovery on.

The json should still be returned but the errors list should be present.

Keyword arguments:
tmp_path -- pytest fixture that creates a temporary directory.
"""
# Saving some files as .txt to avoid that file displaying a syntax error for
# the extension as a whole. Instead, rename it before running this test
# in order to test the error handling.
file_path = TEST_DATA_PATH / "error_syntax_discovery.txt"
temp_dir = tmp_path / "temp_data"
temp_dir.mkdir()
p = temp_dir / "error_syntax_discovery.py"
shutil.copyfile(file_path, p)
actual = runner(["--collect-only", os.fspath(p)])
if actual:
actual = actual[0]
assert actual
assert all(item in actual for item in ("status", "cwd", "error"))
assert actual["status"] == "error"
assert actual["cwd"] == os.fspath(TEST_DATA_PATH)
assert len(actual["error"]) == 2


def test_parameterized_error_collect():
"""Tests pytest discovery on specific file that incorrectly uses parametrize.

The json should still be returned but the errors list should be present.
"""
file_path_str = "error_parametrize_discovery.py"
actual = runner(["--collect-only", file_path_str])
if actual:
actual = actual[0]
assert all(item in actual for item in ("status", "cwd", "error"))
assert actual["status"] == "error"
assert actual["cwd"] == os.fspath(TEST_DATA_PATH)
assert len(actual["error"]) == 2
# def test_import_error(tmp_path):
eleanorjboyd marked this conversation as resolved.
Show resolved Hide resolved
# """Test pytest discovery on a file that has a pytest marker but does not import pytest.

# Copies the contents of a .txt file to a .py file in the temporary directory
# to then run pytest discovery on.

# The json should still be returned but the errors list should be present.

# Keyword arguments:
# tmp_path -- pytest fixture that creates a temporary directory.
# """
# # Saving some files as .txt to avoid that file displaying a syntax error for
# # the extension as a whole. Instead, rename it before running this test
# # in order to test the error handling.
# file_path = TEST_DATA_PATH / "error_pytest_import.txt"
# temp_dir = tmp_path / "temp_data"
# temp_dir.mkdir()
# p = temp_dir / "error_pytest_import.py"
# shutil.copyfile(file_path, p)
# actual_list: Optional[List[Dict[str, Any]]] = runner(
# ["--collect-only", os.fspath(p)]
# )
# assert actual_list
# for actual in actual_list:
# assert all(item in actual for item in ("status", "cwd", "error"))
# assert actual["status"] == "error"
# assert actual["cwd"] == os.fspath(TEST_DATA_PATH)
# assert len(actual["error"]) == 2


# def test_syntax_error(tmp_path):
# """Test pytest discovery on a file that has a syntax error.

# Copies the contents of a .txt file to a .py file in the temporary directory
# to then run pytest discovery on.

# The json should still be returned but the errors list should be present.

# Keyword arguments:
# tmp_path -- pytest fixture that creates a temporary directory.
# """
# # Saving some files as .txt to avoid that file displaying a syntax error for
# # the extension as a whole. Instead, rename it before running this test
# # in order to test the error handling.
# file_path = TEST_DATA_PATH / "error_syntax_discovery.txt"
# temp_dir = tmp_path / "temp_data"
# temp_dir.mkdir()
# p = temp_dir / "error_syntax_discovery.py"
# shutil.copyfile(file_path, p)
# actual = runner(["--collect-only", os.fspath(p)])
# if actual:
# actual = actual[0]
# assert actual
# assert all(item in actual for item in ("status", "cwd", "error"))
# assert actual["status"] == "error"
# assert actual["cwd"] == os.fspath(TEST_DATA_PATH)
# assert len(actual["error"]) == 2


# def test_parameterized_error_collect():
# """Tests pytest discovery on specific file that incorrectly uses parametrize.

# The json should still be returned but the errors list should be present.
# """
# file_path_str = "error_parametrize_discovery.py"
# actual = runner(["--collect-only", file_path_str])
# if actual:
# actual = actual[0]
# assert all(item in actual for item in ("status", "cwd", "error"))
# assert actual["status"] == "error"
# assert actual["cwd"] == os.fspath(TEST_DATA_PATH)
# assert len(actual["error"]) == 2


@pytest.mark.parametrize(
"file, expected_const",
[
(
"param_same_name",
expected_discovery_test_output.param_same_name_expected_output,
),
(
"parametrize_tests.py",
expected_discovery_test_output.parametrize_tests_expected_output,
),
(
"empty_discovery.py",
expected_discovery_test_output.empty_discovery_pytest_expected_output,
),
(
"simple_pytest.py",
expected_discovery_test_output.simple_discovery_pytest_expected_output,
),
(
"unittest_pytest_same_file.py",
expected_discovery_test_output.unit_pytest_same_file_discovery_expected_output,
),
# (
# "param_same_name",
# expected_discovery_test_output.param_same_name_expected_output,
# ),
# (
# "parametrize_tests.py",
# expected_discovery_test_output.parametrize_tests_expected_output,
# ),
# (
# "empty_discovery.py",
# expected_discovery_test_output.empty_discovery_pytest_expected_output,
# ),
# (
# "simple_pytest.py",
# expected_discovery_test_output.simple_discovery_pytest_expected_output,
# ),
# (
# "unittest_pytest_same_file.py",
# expected_discovery_test_output.unit_pytest_same_file_discovery_expected_output,
# ),
(
"unittest_folder",
expected_discovery_test_output.unittest_folder_discovery_expected_output,
Expand Down
4 changes: 2 additions & 2 deletions pythonFiles/vscode_pytest/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,10 +266,10 @@ def build_test_tree(session: pytest.Session) -> TestNode:
test_node = create_test_node(test_case)
if isinstance(test_case.parent, pytest.Class):
try:
test_class_node = class_nodes_dict[test_case.parent.name]
test_class_node = class_nodes_dict[test_case.parent.nodeid]
except KeyError:
test_class_node = create_class_node(test_case.parent)
class_nodes_dict[test_case.parent.name] = test_class_node
class_nodes_dict[test_case.parent.nodeid] = test_class_node
test_class_node["children"].append(test_node)
if test_case.parent.parent:
parent_module = test_case.parent.parent
Expand Down