From a40e6f67b6c718486b3b36c1bf67a4439d740935 Mon Sep 17 00:00:00 2001 From: eleanorjboyd Date: Thu, 7 Dec 2023 13:42:29 -0800 Subject: [PATCH 1/3] unittest: switch to using top dir since test ids are relative to it --- pythonFiles/unittestadapter/discovery.py | 12 +++++++++++- pythonFiles/unittestadapter/utils.py | 15 +++++++++------ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/pythonFiles/unittestadapter/discovery.py b/pythonFiles/unittestadapter/discovery.py index e8f602a22fb3..0482945353e8 100644 --- a/pythonFiles/unittestadapter/discovery.py +++ b/pythonFiles/unittestadapter/discovery.py @@ -86,7 +86,13 @@ def discover_tests( loader = unittest.TestLoader() suite = loader.discover(start_dir, pattern, top_level_dir) - tests, error = build_test_tree(suite, cwd) # test tree built succesfully here. + # If the top level directory is not provided, then use the start directory. + if top_level_dir is None: + top_level_dir = start_dir + + tests, error = build_test_tree( + suite, top_level_dir + ) # test tree built successfully here. except Exception: error.append(traceback.format_exc()) @@ -146,6 +152,10 @@ def post_response( ) if testUuid is not None: # Perform test discovery. + print("payload = discover_tests(start_dir, pattern, top_level_dir, testUuid)") + print( + "EJFB star", start_dir, "pat", pattern, "tl", top_level_dir, "tu", testUuid + ) payload = discover_tests(start_dir, pattern, top_level_dir, testUuid) # Post this discovery payload. post_response(payload, testPort, testUuid) diff --git a/pythonFiles/unittestadapter/utils.py b/pythonFiles/unittestadapter/utils.py index 2c5ebf09abc7..5632e69b09c7 100644 --- a/pythonFiles/unittestadapter/utils.py +++ b/pythonFiles/unittestadapter/utils.py @@ -94,12 +94,13 @@ def build_test_node(path: str, name: str, type_: TestNodeTypeEnum) -> TestNode: def get_child_node( name: str, path: str, type_: TestNodeTypeEnum, root: TestNode ) -> TestNode: - """Find a child node in a test tree given its name and type. If the node doesn't exist, create it.""" + """Find a child node in a test tree given its name, type and path. If the node doesn't exist, create it. + Path is required to distinguish between nodes with the same name and type.""" try: result = next( node for node in root["children"] - if node["name"] == name and node["type_"] == type_ + if node["name"] == name and node["type_"] == type_ and node["path"] == path ) except StopIteration: result = build_test_node(path, name, type_) @@ -109,7 +110,7 @@ def get_child_node( def build_test_tree( - suite: unittest.TestSuite, test_directory: str + suite: unittest.TestSuite, top_level_directory: str ) -> Tuple[Union[TestNode, None], List[str]]: """Build a test tree from a unittest test suite. @@ -152,8 +153,10 @@ def build_test_tree( } """ error = [] - directory_path = pathlib.PurePath(test_directory) - root = build_test_node(test_directory, directory_path.name, TestNodeTypeEnum.folder) + directory_path = pathlib.PurePath(top_level_directory) + root = build_test_node( + top_level_directory, directory_path.name, TestNodeTypeEnum.folder + ) for test_case in get_test_case(suite): test_id = test_case.id() @@ -185,7 +188,7 @@ def build_test_tree( ) # Find/build file node. - path_components = [test_directory] + folders + [py_filename] + path_components = [top_level_directory] + folders + [py_filename] file_path = os.fsdecode(pathlib.PurePath("/".join(path_components))) current_node = get_child_node( py_filename, file_path, TestNodeTypeEnum.file, current_node From e497b9117d11b4d2ab4876989d8523a9f750f883 Mon Sep 17 00:00:00 2001 From: eleanorjboyd Date: Thu, 7 Dec 2023 13:43:43 -0800 Subject: [PATCH 2/3] remove prints --- pythonFiles/unittestadapter/discovery.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pythonFiles/unittestadapter/discovery.py b/pythonFiles/unittestadapter/discovery.py index 0482945353e8..3d1c54ef2a68 100644 --- a/pythonFiles/unittestadapter/discovery.py +++ b/pythonFiles/unittestadapter/discovery.py @@ -152,10 +152,6 @@ def post_response( ) if testUuid is not None: # Perform test discovery. - print("payload = discover_tests(start_dir, pattern, top_level_dir, testUuid)") - print( - "EJFB star", start_dir, "pat", pattern, "tl", top_level_dir, "tu", testUuid - ) payload = discover_tests(start_dir, pattern, top_level_dir, testUuid) # Post this discovery payload. post_response(payload, testPort, testUuid) From 8d9f8a3aed9fcbf5e4e72fb281da17e5c697a33d Mon Sep 17 00:00:00 2001 From: eleanorjboyd Date: Tue, 19 Dec 2023 13:42:56 -0500 Subject: [PATCH 3/3] add tests --- .../.data/utils_complex_tree/__init__.py | 0 .../test_outer_folder/__init__.py | 0 .../test_inner_folder/__init__.py | 0 .../test_utils_complex_tree.py | 8 ++ .../expected_discovery_test_output.py | 85 +++++++++++++++++++ .../tests/unittestadapter/test_discovery.py | 22 +++++ 6 files changed, 115 insertions(+) create mode 100644 pythonFiles/tests/unittestadapter/.data/utils_complex_tree/__init__.py create mode 100644 pythonFiles/tests/unittestadapter/.data/utils_complex_tree/test_outer_folder/__init__.py create mode 100644 pythonFiles/tests/unittestadapter/.data/utils_complex_tree/test_outer_folder/test_inner_folder/__init__.py create mode 100644 pythonFiles/tests/unittestadapter/.data/utils_complex_tree/test_outer_folder/test_inner_folder/test_utils_complex_tree.py diff --git a/pythonFiles/tests/unittestadapter/.data/utils_complex_tree/__init__.py b/pythonFiles/tests/unittestadapter/.data/utils_complex_tree/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/pythonFiles/tests/unittestadapter/.data/utils_complex_tree/test_outer_folder/__init__.py b/pythonFiles/tests/unittestadapter/.data/utils_complex_tree/test_outer_folder/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/pythonFiles/tests/unittestadapter/.data/utils_complex_tree/test_outer_folder/test_inner_folder/__init__.py b/pythonFiles/tests/unittestadapter/.data/utils_complex_tree/test_outer_folder/test_inner_folder/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/pythonFiles/tests/unittestadapter/.data/utils_complex_tree/test_outer_folder/test_inner_folder/test_utils_complex_tree.py b/pythonFiles/tests/unittestadapter/.data/utils_complex_tree/test_outer_folder/test_inner_folder/test_utils_complex_tree.py new file mode 100644 index 000000000000..8f57fb880ff1 --- /dev/null +++ b/pythonFiles/tests/unittestadapter/.data/utils_complex_tree/test_outer_folder/test_inner_folder/test_utils_complex_tree.py @@ -0,0 +1,8 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. +import unittest + + +class TreeOne(unittest.TestCase): + def test_one(self): + assert True diff --git a/pythonFiles/tests/unittestadapter/expected_discovery_test_output.py b/pythonFiles/tests/unittestadapter/expected_discovery_test_output.py index 3043ec158a2e..0b253a084734 100644 --- a/pythonFiles/tests/unittestadapter/expected_discovery_test_output.py +++ b/pythonFiles/tests/unittestadapter/expected_discovery_test_output.py @@ -4,6 +4,7 @@ import os from unittestadapter.utils import TestNodeTypeEnum from .helpers import TEST_DATA_PATH +import pathlib skip_unittest_folder_discovery_output = { "path": os.fspath(TEST_DATA_PATH / "unittest_skip"), @@ -66,3 +67,87 @@ ], "id_": os.fspath(TEST_DATA_PATH / "unittest_skip"), } + +complex_tree_file_path = os.fsdecode( + pathlib.PurePath( + TEST_DATA_PATH, + "utils_complex_tree", + "test_outer_folder", + "test_inner_folder", + "test_utils_complex_tree.py", + ) +) +complex_tree_expected_output = { + "name": "utils_complex_tree", + "type_": TestNodeTypeEnum.folder, + "path": os.fsdecode(pathlib.PurePath(TEST_DATA_PATH, "utils_complex_tree")), + "children": [ + { + "name": "test_outer_folder", + "type_": TestNodeTypeEnum.folder, + "path": os.fsdecode( + pathlib.PurePath( + TEST_DATA_PATH, "utils_complex_tree", "test_outer_folder" + ) + ), + "children": [ + { + "name": "test_inner_folder", + "type_": TestNodeTypeEnum.folder, + "path": os.fsdecode( + pathlib.PurePath( + TEST_DATA_PATH, + "utils_complex_tree", + "test_outer_folder", + "test_inner_folder", + ) + ), + "children": [ + { + "name": "test_utils_complex_tree.py", + "type_": TestNodeTypeEnum.file, + "path": complex_tree_file_path, + "children": [ + { + "name": "TreeOne", + "type_": TestNodeTypeEnum.class_, + "path": complex_tree_file_path, + "children": [ + { + "name": "test_one", + "type_": TestNodeTypeEnum.test, + "path": complex_tree_file_path, + "lineno": "7", + "id_": complex_tree_file_path + + "\\" + + "TreeOne" + + "\\" + + "test_one", + "runID": "utils_complex_tree.test_outer_folder.test_inner_folder.test_utils_complex_tree.TreeOne.test_one", + }, + ], + "id_": complex_tree_file_path + "\\" + "TreeOne", + } + ], + "id_": complex_tree_file_path, + } + ], + "id_": os.fsdecode( + pathlib.PurePath( + TEST_DATA_PATH, + "utils_complex_tree", + "test_outer_folder", + "test_inner_folder", + ) + ), + }, + ], + "id_": os.fsdecode( + pathlib.PurePath( + TEST_DATA_PATH, "utils_complex_tree", "test_outer_folder" + ) + ), + } + ], + "id_": os.fsdecode(pathlib.PurePath(TEST_DATA_PATH, "utils_complex_tree")), +} diff --git a/pythonFiles/tests/unittestadapter/test_discovery.py b/pythonFiles/tests/unittestadapter/test_discovery.py index 7d7db772a4a4..f0276d6e0f0b 100644 --- a/pythonFiles/tests/unittestadapter/test_discovery.py +++ b/pythonFiles/tests/unittestadapter/test_discovery.py @@ -231,3 +231,25 @@ def test_unit_skip() -> None: expected_discovery_test_output.skip_unittest_folder_discovery_output, ) assert "error" not in actual + + +def test_complex_tree() -> None: + """This test specifically tests when different start_dir and top_level_dir are provided.""" + start_dir = os.fsdecode( + pathlib.PurePath( + TEST_DATA_PATH, + "utils_complex_tree", + "test_outer_folder", + "test_inner_folder", + ) + ) + pattern = "test_*.py" + top_level_dir = os.fsdecode(pathlib.PurePath(TEST_DATA_PATH, "utils_complex_tree")) + uuid = "some-uuid" + actual = discover_tests(start_dir, pattern, top_level_dir, uuid) + assert actual["status"] == "success" + assert "error" not in actual + assert is_same_tree( + actual.get("tests"), + expected_discovery_test_output.complex_tree_expected_output, + )