Skip to content

Commit c1ff6c3

Browse files
authored
add to payload to allow error parsing on TS (#21483)
partial fix for #21476, make sure error display correctly. two part fix: fix "errors" to "error" in unittest payload to align with naming everywhere else add "result" and "test" to payload in run and discovery respectively even on error to havae resultResolver handle correctly.
1 parent 8c86417 commit c1ff6c3

5 files changed

Lines changed: 29 additions & 27 deletions

File tree

pythonFiles/tests/unittestadapter/test_discovery.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ def test_simple_discovery() -> None:
132132

133133
assert actual["status"] == "success"
134134
assert is_same_tree(actual.get("tests"), expected)
135-
assert "errors" not in actual
135+
assert "error" not in actual
136136

137137

138138
def test_empty_discovery() -> None:
@@ -146,8 +146,8 @@ def test_empty_discovery() -> None:
146146
actual = discover_tests(start_dir, pattern, None, uuid)
147147

148148
assert actual["status"] == "success"
149-
assert "tests" not in actual
150-
assert "errors" not in actual
149+
assert "tests" in actual
150+
assert "error" not in actual
151151

152152

153153
def test_error_discovery() -> None:
@@ -213,4 +213,4 @@ def test_error_discovery() -> None:
213213

214214
assert actual["status"] == "error"
215215
assert is_same_tree(expected, actual.get("tests"))
216-
assert len(actual.get("errors", [])) == 1
216+
assert len(actual.get("error", [])) == 1

pythonFiles/tests/unittestadapter/test_execution.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ def test_no_ids_run() -> None:
6565
assert all(item in actual for item in ("cwd", "status"))
6666
assert actual["status"] == "success"
6767
assert actual["cwd"] == os.fspath(TEST_DATA_PATH)
68-
if "result" in actual:
68+
if actual["result"] is not None:
6969
assert len(actual["result"]) == 0
7070
else:
7171
raise AssertionError("actual['result'] is None")
@@ -85,7 +85,7 @@ def test_single_ids_run() -> None:
8585
assert all(item in actual for item in ("cwd", "status"))
8686
assert actual["status"] == "success"
8787
assert actual["cwd"] == os.fspath(TEST_DATA_PATH)
88-
assert "result" in actual
88+
assert actual["result"] is not None
8989
result = actual["result"]
9090
assert len(result) == 1
9191
assert id in result
@@ -117,7 +117,7 @@ def test_subtest_run() -> None:
117117
assert all(item in actual for item in ("cwd", "status"))
118118
assert actual["status"] == "success"
119119
assert actual["cwd"] == os.fspath(TEST_DATA_PATH)
120-
assert "result" in actual
120+
assert actual["result"] is not None
121121
result = actual["result"]
122122
assert len(result) == 6
123123
for id in subtests_ids:
@@ -205,7 +205,7 @@ def test_multiple_ids_run(test_ids, pattern, cwd, expected_outcome) -> None:
205205
assert all(item in actual for item in ("cwd", "status"))
206206
assert actual["status"] == "success"
207207
assert actual["cwd"] == cwd
208-
assert "result" in actual
208+
assert actual["result"] is not None
209209
result = actual["result"]
210210
assert len(result) == len(test_ids)
211211
for test_id in test_ids:
@@ -230,7 +230,7 @@ def test_failed_tests():
230230
assert all(item in actual for item in ("cwd", "status"))
231231
assert actual["status"] == "success"
232232
assert actual["cwd"] == os.fspath(TEST_DATA_PATH)
233-
assert "result" in actual
233+
assert actual["result"] is not None
234234
result = actual["result"]
235235
assert len(result) == len(test_ids)
236236
for test_id in test_ids:
@@ -255,7 +255,7 @@ def test_unknown_id():
255255
assert all(item in actual for item in ("cwd", "status"))
256256
assert actual["status"] == "success"
257257
assert actual["cwd"] == os.fspath(TEST_DATA_PATH)
258-
assert "result" in actual
258+
assert actual["result"] is not None
259259
result = actual["result"]
260260
assert len(result) == len(test_ids)
261261
assert "unittest.loader._FailedTest.unknown_id" in result

pythonFiles/unittestadapter/discovery.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ def parse_discovery_cli_args(args: List[str]) -> Tuple[int, Union[str, None]]:
5353
class PayloadDict(TypedDict):
5454
cwd: str
5555
status: Literal["success", "error"]
56-
tests: NotRequired[TestNode]
57-
errors: NotRequired[List[str]]
56+
tests: Optional[TestNode]
57+
error: NotRequired[List[str]]
5858

5959

6060
def discover_tests(
@@ -68,7 +68,7 @@ def discover_tests(
6868
- uuid: UUID sent by the caller of the Python script, that needs to be sent back as an integrity check;
6969
- status: Test discovery status, can be "success" or "error";
7070
- tests: Discoverered tests if any, not present otherwise. Note that the status can be "error" but the payload can still contain tests;
71-
- errors: Discovery errors if any, not present otherwise.
71+
- error: Discovery error if any, not present otherwise.
7272
7373
Payload format for a successful discovery:
7474
{
@@ -86,30 +86,31 @@ def discover_tests(
8686
Payload format when there are errors:
8787
{
8888
"cwd": <test discovery directory>
89-
"errors": [list of errors]
89+
"": [list of errors]
9090
"status": "error",
9191
}
9292
"""
9393
cwd = os.path.abspath(start_dir)
94-
payload: PayloadDict = {"cwd": cwd, "status": "success"}
94+
payload: PayloadDict = {"cwd": cwd, "status": "success", "tests": None}
9595
tests = None
96-
errors: List[str] = []
96+
error: List[str] = []
9797

9898
try:
9999
loader = unittest.TestLoader()
100100
suite = loader.discover(start_dir, pattern, top_level_dir)
101101

102-
tests, errors = build_test_tree(suite, cwd) # test tree built succesfully here.
102+
tests, error = build_test_tree(suite, cwd) # test tree built succesfully here.
103103

104104
except Exception:
105-
errors.append(traceback.format_exc())
105+
error.append(traceback.format_exc())
106106

107-
if tests is not None:
108-
payload["tests"] = tests
107+
# Still include the tests in the payload even if there are errors so that the TS
108+
# side can determine if it is from run or discovery.
109+
payload["tests"] = tests if tests is not None else None
109110

110-
if len(errors):
111+
if len(error):
111112
payload["status"] = "error"
112-
payload["errors"] = errors
113+
payload["error"] = error
113114

114115
return payload
115116

pythonFiles/unittestadapter/execution.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ class TestExecutionStatus(str, enum.Enum):
165165
class PayloadDict(TypedDict):
166166
cwd: str
167167
status: TestExecutionStatus
168-
result: NotRequired[TestResultTypeAlias]
168+
result: Optional[TestResultTypeAlias]
169169
not_found: NotRequired[List[str]]
170170
error: NotRequired[str]
171171

@@ -185,7 +185,7 @@ def run_tests(
185185
cwd = os.path.abspath(start_dir)
186186
status = TestExecutionStatus.error
187187
error = None
188-
payload: PayloadDict = {"cwd": cwd, "status": status}
188+
payload: PayloadDict = {"cwd": cwd, "status": status, "result": None}
189189

190190
try:
191191
# If it's a file, split path and file name.
@@ -312,4 +312,5 @@ def send_run_data(raw_data, port, uuid):
312312
"cwd": cwd,
313313
"status": status,
314314
"error": "No test ids received from buffer",
315+
"result": None,
315316
}

pythonFiles/unittestadapter/utils.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,14 +151,14 @@ def build_test_tree(
151151
"id_": <test_directory path>
152152
}
153153
"""
154-
errors = []
154+
error = []
155155
directory_path = pathlib.PurePath(test_directory)
156156
root = build_test_node(test_directory, directory_path.name, TestNodeTypeEnum.folder)
157157

158158
for test_case in get_test_case(suite):
159159
test_id = test_case.id()
160160
if test_id.startswith("unittest.loader._FailedTest"):
161-
errors.append(str(test_case._exception)) # type: ignore
161+
error.append(str(test_case._exception)) # type: ignore
162162
else:
163163
# Get the static test path components: filename, class name and function name.
164164
components = test_id.split(".")
@@ -206,7 +206,7 @@ def build_test_tree(
206206
if not root["children"]:
207207
root = None
208208

209-
return root, errors
209+
return root, error
210210

211211

212212
def parse_unittest_args(args: List[str]) -> Tuple[str, str, Union[str, None]]:

0 commit comments

Comments
 (0)