From 8ac102a9ef88e9d65dc2cbd105ee5f36fc377b8a Mon Sep 17 00:00:00 2001 From: eleanorjboyd Date: Tue, 24 Sep 2024 15:47:00 -0700 Subject: [PATCH 1/5] Refactor coverage.py methods for accessing --- .../tests/pytestadapter/test_coverage.py | 6 --- .../tests/unittestadapter/test_coverage.py | 6 --- python_files/unittestadapter/execution.py | 33 ++++++-------- python_files/unittestadapter/pvsc_utils.py | 2 - python_files/vscode_pytest/__init__.py | 44 +++++-------------- .../vscode_pytest/run_pytest_script.py | 3 +- .../testController/common/resultResolver.ts | 11 +---- 7 files changed, 26 insertions(+), 79 deletions(-) diff --git a/python_files/tests/pytestadapter/test_coverage.py b/python_files/tests/pytestadapter/test_coverage.py index 31e2be24437e..5dd8a0323b24 100644 --- a/python_files/tests/pytestadapter/test_coverage.py +++ b/python_files/tests/pytestadapter/test_coverage.py @@ -42,9 +42,3 @@ def test_simple_pytest_coverage(): assert focal_function_coverage.get("lines_missed") is not None assert set(focal_function_coverage.get("lines_covered")) == {4, 5, 7, 9, 10, 11, 12, 13, 14, 17} assert set(focal_function_coverage.get("lines_missed")) == {18, 19, 6} - assert ( - focal_function_coverage.get("executed_branches") > 0 - ), "executed_branches are a number greater than 0." - assert ( - focal_function_coverage.get("total_branches") > 0 - ), "total_branches are a number greater than 0." diff --git a/python_files/tests/unittestadapter/test_coverage.py b/python_files/tests/unittestadapter/test_coverage.py index 0089e9ae5504..594aa764370e 100644 --- a/python_files/tests/unittestadapter/test_coverage.py +++ b/python_files/tests/unittestadapter/test_coverage.py @@ -49,9 +49,3 @@ def test_basic_coverage(): assert focal_function_coverage.get("lines_missed") is not None assert set(focal_function_coverage.get("lines_covered")) == {4, 5, 7, 9, 10, 11, 12, 13, 14} assert set(focal_function_coverage.get("lines_missed")) == {6} - assert ( - focal_function_coverage.get("executed_branches") > 0 - ), "executed_branches are a number greater than 0." - assert ( - focal_function_coverage.get("total_branches") > 0 - ), "total_branches are a number greater than 0." diff --git a/python_files/unittestadapter/execution.py b/python_files/unittestadapter/execution.py index 2c49182c8633..c42e9a95e111 100644 --- a/python_files/unittestadapter/execution.py +++ b/python_files/unittestadapter/execution.py @@ -10,7 +10,7 @@ import traceback import unittest from types import TracebackType -from typing import Dict, Iterator, List, Optional, Tuple, Type, Union +from typing import Dict, List, Optional, Tuple, Type, Union # Adds the scripts directory to the PATH as a workaround for enabling shell for test execution. path_var_name = "PATH" if "PATH" in os.environ else "Path" @@ -375,31 +375,26 @@ def send_run_data(raw_data, test_run_pipe): ) if is_coverage_run: - from coverage.plugin import FileReporter - from coverage.report_core import get_analysis_to_report - from coverage.results import Analysis + import coverage if not cov: raise VSCodeUnittestError("Coverage is enabled but cov is not set") cov.stop() cov.save() - analysis_iterator: Iterator[Tuple[FileReporter, Analysis]] = get_analysis_to_report( - cov, None - ) - - file_coverage_map: Dict[str, FileCoverageInfo] = {} - for fr, analysis in analysis_iterator: - file_str: str = fr.filename - executed_branches = analysis.numbers.n_executed_branches - total_branches = analysis.numbers.n_branches - + cov.load() + file_set: set[str] = cov.get_data().measured_files() + file_coverage_map: dict[str, FileCoverageInfo] = {} + for file in file_set: + analysis = cov.analysis2(file) + lines_executable = {int(line_no) for line_no in analysis[1]} + lines_missed = {int(line_no) for line_no in analysis[3]} + lines_covered = lines_executable - lines_missed file_info: FileCoverageInfo = { - "lines_covered": list(analysis.executed), # set - "lines_missed": list(analysis.missing), # set - "executed_branches": executed_branches, # int - "total_branches": total_branches, # int + "lines_covered": list(lines_covered), # list of int + "lines_missed": list(lines_missed), # list of int } - file_coverage_map[file_str] = file_info + file_coverage_map[file] = file_info + payload_cov: CoveragePayloadDict = CoveragePayloadDict( coverage=True, cwd=os.fspath(cwd), diff --git a/python_files/unittestadapter/pvsc_utils.py b/python_files/unittestadapter/pvsc_utils.py index 25088f0cb7a2..8246c580f3ad 100644 --- a/python_files/unittestadapter/pvsc_utils.py +++ b/python_files/unittestadapter/pvsc_utils.py @@ -84,8 +84,6 @@ class EOTPayloadDict(TypedDict): class FileCoverageInfo(TypedDict): lines_covered: List[int] lines_missed: List[int] - executed_branches: int - total_branches: int class CoveragePayloadDict(Dict): diff --git a/python_files/vscode_pytest/__init__.py b/python_files/vscode_pytest/__init__.py index 6f04c45f00e6..92a803190886 100644 --- a/python_files/vscode_pytest/__init__.py +++ b/python_files/vscode_pytest/__init__.py @@ -14,7 +14,6 @@ Any, Dict, Generator, - Iterator, Literal, TypedDict, ) @@ -66,8 +65,6 @@ def __init__(self, message): TEST_RUN_PIPE = os.getenv("TEST_RUN_PIPE") SYMLINK_PATH = None -INCLUDE_BRANCHES = False - def pytest_load_initial_conftests(early_config, parser, args): # noqa: ARG001 global TEST_RUN_PIPE @@ -84,10 +81,6 @@ def pytest_load_initial_conftests(early_config, parser, args): # noqa: ARG001 global IS_DISCOVERY IS_DISCOVERY = True - if "--cov-branch" in args: - global INCLUDE_BRANCHES - INCLUDE_BRANCHES = True - # check if --rootdir is in the args for arg in args: if "--rootdir=" in arg: @@ -366,8 +359,6 @@ def check_skipped_condition(item): class FileCoverageInfo(TypedDict): lines_covered: list[int] lines_missed: list[int] - executed_branches: int - total_branches: int def pytest_sessionfinish(session, exitstatus): @@ -435,41 +426,26 @@ def pytest_sessionfinish(session, exitstatus): ) # send end of transmission token - # send coverageee if enabled + # send coverage if enabled is_coverage_run = os.environ.get("COVERAGE_ENABLED") if is_coverage_run == "True": # load the report and build the json result to return import coverage - from coverage.report_core import get_analysis_to_report - - if TYPE_CHECKING: - from coverage.plugin import FileReporter - from coverage.results import Analysis cov = coverage.Coverage() cov.load() - analysis_iterator: Iterator[tuple[FileReporter, Analysis]] = get_analysis_to_report( - cov, None - ) - + file_set: set[str] = cov.get_data().measured_files() file_coverage_map: dict[str, FileCoverageInfo] = {} - for fr, analysis in analysis_iterator: - file_str: str = fr.filename - executed_branches = analysis.numbers.n_executed_branches - total_branches = analysis.numbers.n_branches - if not INCLUDE_BRANCHES: - print("coverage not run with branches") - # if covearge wasn't run with branches, set the total branches value to -1 to signal that it is not available - executed_branches = 0 - total_branches = -1 - + for file in file_set: + analysis = cov.analysis2(file) + lines_executable = {int(line_no) for line_no in analysis[1]} + lines_missed = {int(line_no) for line_no in analysis[3]} + lines_covered = lines_executable - lines_missed file_info: FileCoverageInfo = { - "lines_covered": list(analysis.executed), # set - "lines_missed": list(analysis.missing), # set - "executed_branches": executed_branches, # int - "total_branches": total_branches, # int + "lines_covered": list(lines_covered), # list of int + "lines_missed": list(lines_missed), # list of int } - file_coverage_map[file_str] = file_info + file_coverage_map[file] = file_info payload: CoveragePayloadDict = CoveragePayloadDict( coverage=True, diff --git a/python_files/vscode_pytest/run_pytest_script.py b/python_files/vscode_pytest/run_pytest_script.py index 9abe3fd6b86c..61a77c51a156 100644 --- a/python_files/vscode_pytest/run_pytest_script.py +++ b/python_files/vscode_pytest/run_pytest_script.py @@ -45,8 +45,7 @@ def run_pytest(args): coverage_enabled = True break if not coverage_enabled: - print("Coverage is enabled, adding branch coverage as an argument.") - args = [*args, "--cov=.", "--cov-branch"] + args = [*args, "--cov=."] run_test_ids_pipe = os.environ.get("RUN_TEST_IDS_PIPE") if run_test_ids_pipe: diff --git a/src/client/testing/testController/common/resultResolver.ts b/src/client/testing/testController/common/resultResolver.ts index 54a21a712133..5e867882a2df 100644 --- a/src/client/testing/testController/common/resultResolver.ts +++ b/src/client/testing/testController/common/resultResolver.ts @@ -149,22 +149,13 @@ export class PythonResultResolver implements ITestResultResolver { const fileCoverageMetrics = value; const linesCovered = fileCoverageMetrics.lines_covered ? fileCoverageMetrics.lines_covered : []; // undefined if no lines covered const linesMissed = fileCoverageMetrics.lines_missed ? fileCoverageMetrics.lines_missed : []; // undefined if no lines missed - const executedBranches = fileCoverageMetrics.executed_branches; - const totalBranches = fileCoverageMetrics.total_branches; const lineCoverageCount = new TestCoverageCount( linesCovered.length, linesCovered.length + linesMissed.length, ); const uri = Uri.file(fileNameStr); - let fileCoverage: FileCoverage; - if (totalBranches === -1) { - // branch coverage was not enabled and should not be displayed - fileCoverage = new FileCoverage(uri, lineCoverageCount); - } else { - const branchCoverageCount = new TestCoverageCount(executedBranches, totalBranches); - fileCoverage = new FileCoverage(uri, lineCoverageCount, branchCoverageCount); - } + const fileCoverage = new FileCoverage(uri, lineCoverageCount); runInstance.addCoverage(fileCoverage); // create detailed coverage array for each file (only line coverage on detailed, not branch) From 1ab47eab0df86567292793c1c53cb86008c444a3 Mon Sep 17 00:00:00 2001 From: eleanorjboyd Date: Tue, 24 Sep 2024 15:54:07 -0700 Subject: [PATCH 2/5] update tests and typescript side --- src/client/testing/testController/common/types.ts | 4 ---- src/test/testing/common/testingAdapter.test.ts | 4 ---- 2 files changed, 8 deletions(-) diff --git a/src/client/testing/testController/common/types.ts b/src/client/testing/testController/common/types.ts index 7846461a46a9..0942d9d2588c 100644 --- a/src/client/testing/testController/common/types.ts +++ b/src/client/testing/testController/common/types.ts @@ -279,10 +279,6 @@ export type FileCoverageMetrics = { lines_covered: number[]; // eslint-disable-next-line camelcase lines_missed: number[]; - // eslint-disable-next-line camelcase - executed_branches: number; - // eslint-disable-next-line camelcase - total_branches: number; }; export type ExecutionTestPayload = { diff --git a/src/test/testing/common/testingAdapter.test.ts b/src/test/testing/common/testingAdapter.test.ts index d0dd5b02d283..dcd45b2e56bc 100644 --- a/src/test/testing/common/testingAdapter.test.ts +++ b/src/test/testing/common/testingAdapter.test.ts @@ -768,8 +768,6 @@ suite('End to End Tests: test adapters', () => { // since only one test was run, the other test in the same file will have missed coverage lines assert.strictEqual(simpleFileCov.lines_covered.length, 3, 'Expected 1 line to be covered in even.py'); assert.strictEqual(simpleFileCov.lines_missed.length, 1, 'Expected 3 lines to be missed in even.py'); - assert.strictEqual(simpleFileCov.executed_branches, 1, 'Expected 3 lines to be missed in even.py'); - assert.strictEqual(simpleFileCov.total_branches, 2, 'Expected 3 lines to be missed in even.py'); return Promise.resolve(); }; @@ -823,8 +821,6 @@ suite('End to End Tests: test adapters', () => { // since only one test was run, the other test in the same file will have missed coverage lines assert.strictEqual(simpleFileCov.lines_covered.length, 3, 'Expected 1 line to be covered in even.py'); assert.strictEqual(simpleFileCov.lines_missed.length, 1, 'Expected 3 lines to be missed in even.py'); - assert.strictEqual(simpleFileCov.executed_branches, 1, 'Expected 3 lines to be missed in even.py'); - assert.strictEqual(simpleFileCov.total_branches, 2, 'Expected 3 lines to be missed in even.py'); return Promise.resolve(); }; From ed793c544be27063ec023420db8236d14827043a Mon Sep 17 00:00:00 2001 From: eleanorjboyd Date: Tue, 24 Sep 2024 17:09:00 -0700 Subject: [PATCH 3/5] fixing type --- python_files/unittestadapter/execution.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python_files/unittestadapter/execution.py b/python_files/unittestadapter/execution.py index c42e9a95e111..e9534d307859 100644 --- a/python_files/unittestadapter/execution.py +++ b/python_files/unittestadapter/execution.py @@ -10,7 +10,7 @@ import traceback import unittest from types import TracebackType -from typing import Dict, List, Optional, Tuple, Type, Union +from typing import Dict, List, Optional, Set, Tuple, Type, Union # Adds the scripts directory to the PATH as a workaround for enabling shell for test execution. path_var_name = "PATH" if "PATH" in os.environ else "Path" @@ -382,7 +382,7 @@ def send_run_data(raw_data, test_run_pipe): cov.stop() cov.save() cov.load() - file_set: set[str] = cov.get_data().measured_files() + file_set: Set[str] = cov.get_data().measured_files() file_coverage_map: dict[str, FileCoverageInfo] = {} for file in file_set: analysis = cov.analysis2(file) From cc6a4a08e0805d0310f50226b3ee86350ae469c5 Mon Sep 17 00:00:00 2001 From: eleanorjboyd Date: Wed, 25 Sep 2024 13:55:52 -0700 Subject: [PATCH 4/5] fix path for windows --- src/client/testing/testController/common/resultResolver.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/client/testing/testController/common/resultResolver.ts b/src/client/testing/testController/common/resultResolver.ts index 5e867882a2df..0788c224b0cc 100644 --- a/src/client/testing/testController/common/resultResolver.ts +++ b/src/client/testing/testController/common/resultResolver.ts @@ -133,11 +133,6 @@ export class PythonResultResolver implements ITestResultResolver { } else { this._resolveExecution(payload as ExecutionTestPayload, runInstance); } - if ('coverage' in payload) { - // coverage data is sent once per connection - traceVerbose('Coverage data received.'); - this._resolveCoverage(payload as CoveragePayload, runInstance); - } } public _resolveCoverage(payload: CoveragePayload, runInstance: TestRun): void { @@ -180,7 +175,7 @@ export class PythonResultResolver implements ITestResultResolver { detailedCoverageArray.push(statementCoverage); } - this.detailedCoverageMap.set(fileNameStr, detailedCoverageArray); + this.detailedCoverageMap.set(uri.fsPath, detailedCoverageArray); } } From 0ba73d2818ec13e8042958cf3c4d1c2227516d8d Mon Sep 17 00:00:00 2001 From: eleanorjboyd Date: Wed, 25 Sep 2024 14:00:49 -0700 Subject: [PATCH 5/5] fix typing --- python_files/unittestadapter/execution.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python_files/unittestadapter/execution.py b/python_files/unittestadapter/execution.py index e9534d307859..7884c80d84d9 100644 --- a/python_files/unittestadapter/execution.py +++ b/python_files/unittestadapter/execution.py @@ -383,7 +383,7 @@ def send_run_data(raw_data, test_run_pipe): cov.save() cov.load() file_set: Set[str] = cov.get_data().measured_files() - file_coverage_map: dict[str, FileCoverageInfo] = {} + file_coverage_map: Dict[str, FileCoverageInfo] = {} for file in file_set: analysis = cov.analysis2(file) lines_executable = {int(line_no) for line_no in analysis[1]}