Skip to content

Commit

Permalink
Merge pull request #35 from xenserver/add-coveragerc-mark-not-covered…
Browse files Browse the repository at this point in the history
…-branches

CP-41819: Py3: Collect, check and report code coverage from Python3 unit test runs
  • Loading branch information
bernhardkaindl authored Jan 10, 2024
2 parents 33a45f5 + 0ac6504 commit 2390ca0
Show file tree
Hide file tree
Showing 9 changed files with 100 additions and 14 deletions.
34 changes: 34 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[run]
source =
xen-bugtool
tests/

[report]
# Regular expressions for lines to exclude from consideration
exclude_lines =
# Don't complain if tests don't hit catch-all exception handlers:
except:
except Exception
except IOError
# Have to re-enable the standard pragma
pragma: no cover

# Enable these selectively if you want to allow these raises without cover:
# (If you want no complaint when tests don't hit raising these Assertions)
# raise AssertionError
# raise NotImplementedError
# raise RuntimeError
# raise ValueError
# \<assert\>.*

# Don't complain if non-runnable code isn't run:
if 0:
if __name__ == .__main__.:
if TYPE_CHECKING:
# skip any line with a `pass` (such as may be used for @abstractmethod or @suffixed_method)
pass

precision = 1
include =
xen-bugtool
tests/*
23 changes: 23 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,10 @@ jobs:
name: "Python3: Pre-Commit Suite"
runs-on: ubuntu-22.04
steps:

- uses: actions/checkout@v3
with:
fetch-depth: 0 # For diff-cover to get the changed lines: origin/master..HEAD

# https://www.python4data.science/en/latest/productive/git/advanced/hooks/ci.html
- uses: actions/setup-python@v4
Expand All @@ -91,3 +94,23 @@ jobs:
env:
# Skip the no-commit-to-branch check inside of GitHub CI (for CI on merge to master)
SKIP: no-commit-to-branch

- name: Pytest coverage comment
if: ${{ github.actor != 'nektos/act' }}
uses: MishaKav/pytest-coverage-comment@main
with:
junitxml-path: .git/pytest.xml
pytest-xml-coverage-path: .git/coverage.xml
unique-id-for-comment: pre-commit-coverage
title: https://github.com/marketplace/actions/pytest-coverage-comment

- name: Upload coverage reports to Codecov
if: ${{ github.actor != 'nektos/act' }}
uses: codecov/codecov-action@v3
with:
directory: .git
env_vars: OS,PYTHON
fail_ci_if_error: true
flags: unittest
name: coverage
verbose: true
31 changes: 30 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,39 @@ repos:
- id: pytest
name: check that the Xen-Bugtool Test Environment passes
entry: env PYTHONDEVMODE=yes python3 -m pytest tests/unit
--cov xen-bugtool
--cov tests/unit
--junitxml=.git/pytest.xml
--cov-report term-missing
--cov-report html:.git/coverage.html
--cov-report xml:.git/coverage.xml
require_serial: true
pass_filenames: false
language: python
types: [python]
additional_dependencies: [defusedxml, pytest, lxml, XenAPI]
additional_dependencies: [coverage, defusedxml, pytest-coverage, lxml, XenAPI]


- id: diff-cover
name: check that that the changed lines are covered by tests
entry: diff-cover --ignore-whitespace --compare-branch=origin/master
--show-uncovered --html-report .git/coverage-diff.html
--fail-under 100 .git/coverage.xml
require_serial: true
pass_filenames: false
language: python
types: [python]
additional_dependencies: [diff-cover]


- id: coverage-report
name: check coverage report for minimum overall coverage
entry: coverage report --fail-under 55 #| tee .git/coverage.txt
require_serial: true
pass_filenames: false
language: python
types: [python]
additional_dependencies: [coverage]
- repo: https://github.com/PyCQA/autoflake
rev: v2.2.1
hooks:
Expand Down
6 changes: 3 additions & 3 deletions tests/integration/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ def run_test_functions_with_private_tmpfs_output_directory():
os.chdir(BUGTOOL_OUTPUT_DIR)
# Assert that the test case did not leave any unchecked output file as in the output directory:
remaining_files = []
for currentpath, _, files in os.walk("."):
for current_path, _, files in os.walk("."): # pragma: no cover
for file in files:
remaining_files.append(os.path.join(currentpath, file))
if remaining_files:
remaining_files.append(os.path.join(current_path, file)) # pragma: no cover
if remaining_files: # pragma: no cover
print("Remaining (possibly unchecked) files found:")
print(remaining_files)
os.chdir(BUGTOOL_OUTPUT_DIR)
Expand Down
6 changes: 3 additions & 3 deletions tests/integration/namespace_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def unshare(flags):
libc = ctypes.CDLL(None, use_errno=True)
libc.unshare.argtypes = [ctypes.c_int]
rc = libc.unshare(flags)
if rc != 0:
if rc != 0: # pragma: no cover
errno = ctypes.get_errno()
raise OSError(errno, os.strerror(errno), flags)

Expand All @@ -33,7 +33,7 @@ def mount(source="none", target="", fs="", flags=0, options=""):
)
print("mount -t " + fs + " -o '" + options + "' " + source + "\t" + target)
result = libc.mount(source.encode(), target.encode(), fs.encode(), flags, options.encode())
if result < 0:
if result < 0: # pragma: no cover
errno = ctypes.get_errno()
raise OSError(errno, "mount " + target + " (options=" + options + "): " + os.strerror(errno))

Expand All @@ -42,7 +42,7 @@ def umount(target):
"""Wrapper for the Linux umount system call, supports Python2.7 and Python3.x"""
libc = ctypes.CDLL(None, use_errno=True)
result = libc.umount(ctypes.c_char_p(target.encode()))
if result < 0:
if result < 0: # pragma: no cover
errno = ctypes.get_errno()
raise OSError(errno, "umount " + target + ": " + os.strerror(errno))

Expand Down
8 changes: 4 additions & 4 deletions tests/integration/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

# pyright: ignore[reportMissingImports]
if sys.version_info.major == 2:
from commands import getstatusoutput # type:ignore[import-not-found]
from commands import getstatusoutput # type:ignore[import-not-found] # pragma: no cover
else:
from subprocess import getstatusoutput

Expand Down Expand Up @@ -57,12 +57,12 @@ def assert_content_from_dom0_template(path, control_path=None):
print(control)
if os.path.isdir(path):
result = filecmp.dircmp(path, control)
if result.diff_files or result.right_only:
if result.diff_files or result.right_only: # pragma: no cover
print(result.report)
raise RuntimeError("Missing or Differing files found in " + path)
else:
if not filecmp.cmp(path, control):
os.system("cat " + path)
os.system("cat " + path) # pragma: no cover
raise RuntimeError(control)
# Remove verified output files/directories. Untested files will remain and cause the testcase to FAIL:
try:
Expand All @@ -71,7 +71,7 @@ def assert_content_from_dom0_template(path, control_path=None):
shutil.rmtree(path)


def extract(zip_or_tar_archive, archive_type):
def extract(zip_or_tar_archive, archive_type): # pragma: no cover
"""Extract a passed zip, tar or tar.bz2 archive into the current working directory"""
if sys.version_info > (3, 0):
if archive_type == "zip" and os.environ.get("GITHUB_ACTION"):
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def imported_bugtool(testdir):
def import_from_file(module_name, file_path):
import sys

if sys.version_info.major == 2:
if sys.version_info.major == 2: # pragma: no cover
import imp # pylint: disable=deprecated-module # pyright: ignore[reportMissingImports]

return imp.load_source(module_name, file_path)
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/test_xapidb_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,5 +80,5 @@ def test_xapi_database_filter(bugtool):

# Double-check with parseString(): Its output will differ between Py2/Py3
# though, so we will use it for one language version at a time:
if sys.version_info < (3, 0):
if sys.version_info < (3, 0): # pragma: no cover
assert xml.dom.minidom.parseString(filtered).toprettyxml(indent=" ") == expected
2 changes: 1 addition & 1 deletion xen-bugtool
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ from xml.etree.ElementTree import Element

import defusedxml.sax

if sys.version_info.major == 2:
if sys.version_info.major == 2: # pragma: no cover
from commands import getoutput # pyright: ignore[reportMissingImports]
from urllib import urlopen # type:ignore[attr-defined]

Expand Down

1 comment on commit 2390ca0

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage

https://github.com/marketplace/actions/pytest-coverage-comment
FileStmtsMissCoverMissing
__init__.py00100% 
conftest.py300100% 
test_dir_list.py110100% 
test_fs_funcs.py80100% 
test_load_plugins.py70100% 
test_output.py430100% 
test_process_output.py80100% 
test_xapidb_filter.py170100% 
xen-bugtool152472952%95, 100–101, 410, 490–491, 493–494, 511, 517, 540, 551–552, 555–556, 598, 602–604, 608, 610–614, 616–619, 628–630, 633, 652–653, 656, 658–662, 664–665, 668–669, 673–674, 676–677, 681–684, 686–689, 692–694, 696–697, 701–703, 706–707, 716, 718, 720–723, 725–727, 729–730, 734–735, 737, 739–745, 749–750, 752–756, 761–769, 771–773, 775–777, 779–780, 782, 797, 799–803, 805–806, 808, 810, 812–835, 838–842, 844, 846–867, 870–871, 873, 875, 878, 880–889, 891, 893–896, 898–908, 910–926, 928–932, 934–940, 943–972, 974–984, 986–989, 991–1011, 1013–1016, 1018, 1020, 1022–1023, 1025–1026, 1028, 1043–1044, 1046–1047, 1051–1052, 1054–1055, 1057, 1059, 1061–1062, 1064–1065, 1067–1076, 1079–1085, 1088–1089, 1091–1092, 1101–1102, 1104–1105, 1109, 1131–1134, 1136–1140, 1142–1149, 1151, 1153–1156, 1158, 1161–1163, 1165–1171, 1174–1176, 1180–1181, 1183–1184, 1186–1188, 1191–1192, 1195, 1197–1198, 1200, 1202, 1204–1205, 1209–1212, 1215, 1218, 1221–1223, 1226–1230, 1233–1234, 1237–1240, 1246–1252, 1255–1259, 1261–1277, 1280–1288, 1291–1292, 1294, 1296–1297, 1299–1307, 1310, 1312–1315, 1317, 1319–1320, 1354, 1382, 1397, 1405–1406, 1410–1412, 1414, 1417, 1419–1421, 1423–1427, 1429, 1433, 1436, 1439–1445, 1447, 1449–1453, 1459–1461, 1463–1468, 1471–1475, 1479–1480, 1482, 1499–1500, 1502, 1504–1505, 1507–1509, 1511–1518, 1520–1525, 1529–1530, 1532, 1534, 1536, 1552–1553, 1555, 1557–1559, 1562–1563, 1565, 1567–1569, 1572–1573, 1575, 1577–1580, 1583–1593, 1596–1600, 1610, 1622, 1632, 1636, 1647, 1671–1673, 1685–1688, 1696, 1711, 1715–1719, 1724–1726, 1739, 1745, 1755–1761, 1778, 1799–1802, 1804–1805, 1817, 1877, 1896, 1898, 1900, 1903–1911, 1914–1915, 1918–1925, 1927–1928, 1930, 1934–1935, 1939, 1943–1945, 1949–1950, 1953, 1957, 1962, 1968–1969, 1971, 1975, 1977–1980, 1983–1993, 1997–1998, 2002, 2004, 2027–2036, 2039, 2089–2091, 2094–2096, 2108, 2127–2129, 2169–2173, 2180, 2182–2185, 2189, 2203
TOTAL164872955% 

Tests Skipped Failures Errors Time
10 0 💤 0 ❌ 0 🔥 1.086s ⏱️

Please sign in to comment.