dotfiles/vscode/.vscode/extensions/ms-python.python-2024.10.0-darwin-arm64/python_files/unittestadapter/discovery.py
Errol Sancaktar 5f8db31398 alacritty
2024-07-15 17:06:13 -06:00

128 lines
3.8 KiB
Python

# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
import os
import pathlib
import sys
import traceback
import unittest
from typing import List, Optional
script_dir = pathlib.Path(__file__).parent.parent
sys.path.append(os.fspath(script_dir))
# If I use from utils then there will be an import error in test_discovery.py.
from unittestadapter.pvsc_utils import ( # noqa: E402
VSCodeUnittestError,
build_test_tree,
parse_unittest_args,
send_post_request,
DiscoveryPayloadDict,
EOTPayloadDict,
)
def discover_tests(
start_dir: str,
pattern: str,
top_level_dir: Optional[str],
) -> DiscoveryPayloadDict:
"""Returns a dictionary containing details of the discovered tests.
The returned dict has the following keys:
- cwd: Absolute path to the test start directory;
- status: Test discovery status, can be "success" or "error";
- tests: Discoverered tests if any, not present otherwise. Note that the status can be "error" but the payload can still contain tests;
- error: Discovery error if any, not present otherwise.
Payload format for a successful discovery:
{
"status": "success",
"cwd": <test discovery directory>,
"tests": <test tree>
}
Payload format for a successful discovery with no tests:
{
"status": "success",
"cwd": <test discovery directory>,
}
Payload format when there are errors:
{
"cwd": <test discovery directory>
"": [list of errors]
"status": "error",
}
"""
cwd = os.path.abspath(start_dir)
if "/" in start_dir: # is a subdir
parent_dir = os.path.dirname(start_dir)
sys.path.insert(0, parent_dir)
else:
sys.path.insert(0, cwd)
payload: DiscoveryPayloadDict = {"cwd": cwd, "status": "success", "tests": None}
tests = None
error: List[str] = []
try:
loader = unittest.TestLoader()
suite = loader.discover(start_dir, pattern, top_level_dir)
# If the top level directory is not provided, then use the start directory.
if top_level_dir is None:
top_level_dir = start_dir
# Get abspath of top level directory for build_test_tree.
top_level_dir = os.path.abspath(top_level_dir)
tests, error = build_test_tree(suite, top_level_dir) # test tree built successfully here.
except Exception:
error.append(traceback.format_exc())
# Still include the tests in the payload even if there are errors so that the TS
# side can determine if it is from run or discovery.
payload["tests"] = tests if tests is not None else None
if len(error):
payload["status"] = "error"
payload["error"] = error
return payload
if __name__ == "__main__":
# Get unittest discovery arguments.
argv = sys.argv[1:]
index = argv.index("--udiscovery")
(
start_dir,
pattern,
top_level_dir,
_verbosity,
_failfast,
_locals,
) = parse_unittest_args(argv[index + 1 :])
test_run_pipe = os.getenv("TEST_RUN_PIPE")
if not test_run_pipe:
error_msg = (
"UNITTEST ERROR: TEST_RUN_PIPE is not set at the time of unittest trying to send data. "
"Please confirm this environment variable is not being changed or removed "
"as it is required for successful test discovery and execution."
f"TEST_RUN_PIPE = {test_run_pipe}\n"
)
print(error_msg, file=sys.stderr)
raise VSCodeUnittestError(error_msg)
# Perform test discovery.
payload = discover_tests(start_dir, pattern, top_level_dir)
# Post this discovery payload.
send_post_request(payload, test_run_pipe)
# Post EOT token.
eot_payload: EOTPayloadDict = {"command_type": "discovery", "eot": True}
send_post_request(eot_payload, test_run_pipe)