Skip to content

Commit

Permalink
Respect [tool.coverage.report] omit in coverage view (#24466)
Browse files Browse the repository at this point in the history
fixes: #24366

also adds a missing test dependency to the requirements file, and moves
how to import the NoSource exception
  • Loading branch information
eleanorjboyd authored Nov 19, 2024
1 parent 8ac716d commit 2fed954
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 9 deletions.
2 changes: 2 additions & 0 deletions build/test-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ django-stubs
# for coverage
coverage
pytest-cov
pytest-json


# for pytest-describe related tests
pytest-describe
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

[tool.coverage.report]
omit = ["test_ignore.py"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

def test_to_ignore():
assert True
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

def test_simple():
assert True


def untouched_function():
return 1
52 changes: 45 additions & 7 deletions python_files/tests/pytestadapter/test_coverage.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
import json
import os
import pathlib
import sys
Expand Down Expand Up @@ -43,21 +44,21 @@ def test_simple_pytest_coverage():
assert focal_function_coverage.get("lines_covered") is not None
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 len(set(focal_function_coverage.get("lines_missed"))) >= 3


coverage_file_path = TEST_DATA_PATH / "coverage_gen" / "coverage.json"
coverage_gen_file_path = TEST_DATA_PATH / "coverage_gen" / "coverage.json"


@pytest.fixture
def cleanup_coverage_file():
def cleanup_coverage_gen_file():
# delete the coverage file if it exists as part of test cleanup
yield
if os.path.exists(coverage_file_path): # noqa: PTH110
os.remove(coverage_file_path) # noqa: PTH107
if os.path.exists(coverage_gen_file_path): # noqa: PTH110
os.remove(coverage_gen_file_path) # noqa: PTH107


def test_coverage_gen_report(cleanup_coverage_file): # noqa: ARG001
def test_coverage_gen_report(cleanup_coverage_gen_file): # noqa: ARG001
"""
Test coverage payload is correct for simple pytest example. Output of coverage run is below.
Expand All @@ -73,6 +74,7 @@ def test_coverage_gen_report(cleanup_coverage_file): # noqa: ARG001
args = ["--cov-report=json"]
env_add = {"COVERAGE_ENABLED": "True"}
cov_folder_path = TEST_DATA_PATH / "coverage_gen"
print("cov_folder_path", cov_folder_path)
actual = runner_with_cwd_env(args, cov_folder_path, env_add)
assert actual
coverage = actual[-1]
Expand All @@ -87,4 +89,40 @@ def test_coverage_gen_report(cleanup_coverage_file): # noqa: ARG001
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 that the coverage file was created at the right path
assert os.path.exists(coverage_file_path) # noqa: PTH110
assert os.path.exists(coverage_gen_file_path) # noqa: PTH110


def test_coverage_w_omit_config():
"""
Test the coverage report generation with omit configuration.
folder structure of coverage_w_config
├── coverage_w_config
│ ├── test_ignore.py
│ ├── test_ran.py
│ └── pyproject.toml
pyproject.toml file with the following content:
[tool.coverage.report]
omit = [
"test_ignore.py",
]
Assertions:
- The coverage report is generated.
- The coverage report contains results.
- Only one file is reported in the coverage results.
"""
env_add = {"COVERAGE_ENABLED": "True"}
cov_folder_path = TEST_DATA_PATH / "coverage_w_config"
print("cov_folder_path", cov_folder_path)
actual = runner_with_cwd_env([], cov_folder_path, env_add)
assert actual
print("actual", json.dumps(actual, indent=2))
coverage = actual[-1]
assert coverage
results = coverage["result"]
assert results
# assert one file is reported and one file (as specified in pyproject.toml) is omitted
assert len(results) == 1
14 changes: 12 additions & 2 deletions python_files/vscode_pytest/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -442,17 +442,27 @@ def pytest_sessionfinish(session, exitstatus):
if is_coverage_run == "True":
# load the report and build the json result to return
import coverage
from coverage.exceptions import NoSource
from coverage import exceptions

cov = coverage.Coverage()
cov.load()

file_set: set[str] = cov.get_data().measured_files()
file_coverage_map: dict[str, FileCoverageInfo] = {}

# remove files omitted per coverage report config if any
omit_files = cov.config.report_omit
if omit_files:
omit_files = set(omit_files)
# convert to absolute paths, check against file set
omit_files = {os.fspath(pathlib.Path(file).absolute()) for file in omit_files}
print("Files to omit from reporting", omit_files)
file_set = file_set - omit_files

for file in file_set:
try:
analysis = cov.analysis2(file)
except NoSource:
except exceptions.NoSource:
# as per issue 24308 this best way to handle this edge case
continue
lines_executable = {int(line_no) for line_no in analysis[1]}
Expand Down

0 comments on commit 2fed954

Please sign in to comment.