Add coverage reporting to the test suite

- the nox session "test-coverage" triggers further nox sessions
  that run the test suite for all supported Python versions
- the nox session "_test-coverage-run" runs the test suite for
  a particular Python version using the coverage tool
- the nox session "_test-coverage-report" combines the individual
  coverage reports
This commit is contained in:
Alexander Hess 2024-09-10 02:01:23 +02:00
parent 01d270e39c
commit 6945cdef0a
Signed by: alexander
GPG key ID: 344EA5AB10D868E0
4 changed files with 81 additions and 9 deletions

1
.gitignore vendored
View file

@ -1,4 +1,5 @@
.cache/
dist/
poetry.toml
**/__pycache__/
.venv/

View file

@ -2,6 +2,7 @@
import collections
import pathlib
import random
import re
import tempfile
from collections.abc import Mapping
@ -145,20 +146,22 @@ def lint(session: nox.Session) -> None:
session.run("ruff", "check", *locations)
TEST_DEPENDENCIES = (
"packaging",
"pytest",
"pytest-cov",
"semver",
"xdoctest",
)
@nox_session(python=SUPPORTED_PYTHONS)
def test(session: nox.Session) -> None:
"""Test code with `pytest`."""
start(session)
install_unpinned(session, "-e", ".") # "-e" makes session reuseable
install_pinned(
session,
"packaging",
"pytest",
"pytest-cov",
"semver",
"xdoctest",
)
install_pinned(session, *TEST_DEPENDENCIES)
args = session.posargs or (
"--cov",
@ -169,6 +172,58 @@ def test(session: nox.Session) -> None:
session.run("pytest", *args)
_magic_number = random.randint(0, 987654321) # noqa: S311
@nox_session(name="test-coverage", python=MAIN_PYTHON, reuse_venv=True)
def test_coverage(session: nox.Session) -> None:
"""Report the combined coverage statistics.
Run the test suite for all supported Python versions
and combine the coverage statistics.
"""
install_pinned(session, "coverage")
session.run("python", "-m", "coverage", "erase")
for version in SUPPORTED_PYTHONS:
session.notify(f"_test-coverage-run-{version}", (_magic_number,))
session.notify("_test-coverage-report", (_magic_number,))
@nox_session(name="_test-coverage-run", python=SUPPORTED_PYTHONS, reuse_venv=False)
def test_coverage_run(session: nox.Session) -> None:
"""Measure the test coverage."""
do_not_reuse(session)
do_not_run_directly(session)
start(session)
session.install(".")
install_pinned(session, "coverage", *TEST_DEPENDENCIES)
session.run(
"python",
"-m",
"coverage",
"run",
"-m",
"pytest",
TESTS_LOCATION,
)
@nox_session(name="_test-coverage-report", python=MAIN_PYTHON, reuse_venv=True)
def test_coverage_report(session: nox.Session) -> None:
"""Report the combined coverage statistics."""
do_not_run_directly(session)
install_pinned(session, "coverage")
session.run("python", "-m", "coverage", "combine")
session.run("python", "-m", "coverage", "report", "--fail-under=100")
@nox_session(name="test-docstrings", python=MAIN_PYTHON)
def test_docstrings(session: nox.Session) -> None:
"""Test docstrings with `xdoctest`."""
@ -179,6 +234,21 @@ def test_docstrings(session: nox.Session) -> None:
session.run("xdoctest", "src/lalib")
def do_not_reuse(session: nox.Session, *, raise_error: bool = True) -> None:
"""Do not reuse a session with the "-r" flag."""
if session._runner.venv._reused: # noqa:SLF001
if raise_error:
session.error('The session must be run without the "-r" flag')
else:
session.warn('The session must be run without the "-r" flag')
def do_not_run_directly(session: nox.Session) -> None:
"""Do not run a session with `nox -s SESSION_NAME` directly."""
if not session.posargs or session.posargs[0] != _magic_number:
session.error("This session must not be run directly")
def start(session: nox.Session) -> None:
"""Show generic info about a session."""
if session.posargs:

2
poetry.lock generated
View file

@ -1048,4 +1048,4 @@ tests-strict = ["pytest (==4.6.0)", "pytest (==6.2.5)", "pytest-cov (==3.0.0)"]
[metadata]
lock-version = "2.0"
python-versions = "^3.9"
content-hash = "3648b3426753e3e36e575d6b08fe8ab1b5f5443dcf2d1effaed5e921cdb40933"
content-hash = "41aa1b0224786397f339cd01099c1a687cb57e16898426ef101fd66247d3bd5c"

View file

@ -60,6 +60,7 @@ pydoclint = { extras = ["flake8"], version = "^0.5" }
ruff = "^0.6"
# Test suite
coverage = "^7.6"
packaging = "^24.1" # to test the version identifier
pytest = "^8.3"
pytest-cov = "^5.0"