🧪 Add local test running infra
This commit is contained in:
+35
@@ -0,0 +1,35 @@
|
||||
[html]
|
||||
show_contexts = true
|
||||
skip_covered = false
|
||||
|
||||
[paths]
|
||||
_site-packages-to-src-mapping =
|
||||
src
|
||||
*/src
|
||||
*\src
|
||||
*/lib/pypy*/site-packages
|
||||
*/lib/python*/site-packages
|
||||
*\Lib\site-packages
|
||||
|
||||
[report]
|
||||
# `fail_under` is set here temporarily until it can be dropped:
|
||||
fail_under = 28
|
||||
skip_covered = true
|
||||
skip_empty = true
|
||||
show_missing = true
|
||||
exclude_also =
|
||||
^\s*@pytest\.mark\.xfail
|
||||
|
||||
[run]
|
||||
branch = true
|
||||
cover_pylib = false
|
||||
# https://coverage.rtfd.io/en/latest/contexts.html#dynamic-contexts
|
||||
# dynamic_context = test_function # conflicts with `pytest-cov` if set here
|
||||
parallel = true
|
||||
plugins =
|
||||
covdefaults
|
||||
relative_files = true
|
||||
source =
|
||||
.
|
||||
source_pkgs =
|
||||
normalize_needed_jobs_status
|
||||
@@ -0,0 +1,11 @@
|
||||
[dependency-groups]
|
||||
testing = [
|
||||
'covdefaults', # coveragepy settings as a plugin
|
||||
'coverage', # accessed directly from tox
|
||||
'coverage-enable-subprocess', # coveragepy plugin
|
||||
'pytest', # test runner
|
||||
'pytest-cov', # coveragepy integration
|
||||
'pytest-mock', # `mocker` fixture
|
||||
'pytest-subtests', # allows marking bits of test functions as subtests
|
||||
'pytest-xdist', # parallelism
|
||||
]
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
[pytest]
|
||||
addopts =
|
||||
# `pytest-xdist`:
|
||||
--numprocesses=auto
|
||||
# NOTE: the plugin disabled because it's slower with so few tests
|
||||
--numprocesses=0
|
||||
|
||||
# Show 10 slowest invocations:
|
||||
--durations=10
|
||||
|
||||
# Report all the things == -rxXs:
|
||||
-ra
|
||||
|
||||
# Show values of the local vars in errors/tracebacks:
|
||||
--showlocals
|
||||
|
||||
# Autocollect and invoke the doctests from all modules:
|
||||
# https://docs.pytest.org/en/stable/doctest.html
|
||||
--doctest-modules
|
||||
|
||||
# Pre-load the `pytest-cov` plugin early:
|
||||
-p pytest_cov
|
||||
|
||||
# `pytest-cov`:
|
||||
--cov
|
||||
--cov-config=.coveragerc
|
||||
--cov-context=test
|
||||
--no-cov-on-fail
|
||||
|
||||
# Fail on config parsing warnings:
|
||||
# --strict-config
|
||||
|
||||
# Fail on non-existing markers:
|
||||
# * Deprecated since v6.2.0 but may be reintroduced later covering a
|
||||
# broader scope:
|
||||
# --strict
|
||||
# * Exists since v4.5.0 (advised to be used instead of `--strict`):
|
||||
--strict-markers
|
||||
|
||||
doctest_optionflags = ALLOW_UNICODE ELLIPSIS
|
||||
|
||||
# Marks tests with an empty parameterset as xfail(run=False)
|
||||
empty_parameter_set_mark = xfail
|
||||
|
||||
faulthandler_timeout = 30
|
||||
|
||||
filterwarnings =
|
||||
error
|
||||
|
||||
# https://docs.pytest.org/en/stable/usage.html#creating-junitxml-format-files
|
||||
junit_duration_report = call
|
||||
# xunit1 contains more metadata than xunit2 so it's better for CI UIs:
|
||||
junit_family = xunit1
|
||||
junit_logging = all
|
||||
junit_log_passing_tests = true
|
||||
junit_suite_name = alls_green_test_suite
|
||||
|
||||
# A mapping of markers to their descriptions allowed in strict mode:
|
||||
markers =
|
||||
|
||||
minversion = 6.1.0
|
||||
|
||||
# Optimize pytest's lookup by restricting potentially deep dir tree scan:
|
||||
norecursedirs =
|
||||
build
|
||||
dependencies
|
||||
dist
|
||||
docs
|
||||
.*
|
||||
*.egg
|
||||
*.egg-info
|
||||
*/*.egg-info
|
||||
*/**/*.egg-info
|
||||
*.dist-info
|
||||
*/*.dist-info
|
||||
*/**/*.dist-info
|
||||
|
||||
testpaths = tests/
|
||||
|
||||
xfail_strict = true
|
||||
@@ -0,0 +1,8 @@
|
||||
"""Initial test infra smoke tests."""
|
||||
|
||||
import normalize_needed_jobs_status # pth via editable install in tox
|
||||
|
||||
|
||||
def test_smoke() -> None:
|
||||
"""Check that the imported module is truthy."""
|
||||
assert normalize_needed_jobs_status
|
||||
@@ -0,0 +1,109 @@
|
||||
[tox]
|
||||
isolated_build = true
|
||||
# Version 4.22 is the first one to implement support for dependency groups:
|
||||
minversion = 4.22
|
||||
|
||||
|
||||
[python-cli-options]
|
||||
byte-warnings = -b
|
||||
byte-errors = -bb
|
||||
max-isolation = -E -s -I
|
||||
some-isolation = -E -s
|
||||
warnings-to-errors = -Werror
|
||||
|
||||
|
||||
[testenv]
|
||||
description = Run pytest under {envpython}
|
||||
dependency_groups =
|
||||
testing
|
||||
commands =
|
||||
{envpython} \
|
||||
{[python-cli-options]byte-errors} \
|
||||
{[python-cli-options]max-isolation} \
|
||||
{[python-cli-options]warnings-to-errors} \
|
||||
-W 'ignore:Coverage failure::pytest_cov.plugin' \
|
||||
-m pytest \
|
||||
{tty:--color=yes} \
|
||||
{posargs:--cov-report=html:{envtmpdir}{/}htmlcov{/}}
|
||||
commands_post =
|
||||
-{envpython} \
|
||||
{[python-cli-options]byte-errors} \
|
||||
{[python-cli-options]max-isolation} \
|
||||
{[python-cli-options]warnings-to-errors} \
|
||||
-c \
|
||||
'import atexit, os, sys; \
|
||||
os.getenv("GITHUB_ACTIONS") == "true" or sys.exit(); \
|
||||
import coverage; \
|
||||
gh_summary_fd = open(\
|
||||
os.environ["GITHUB_STEP_SUMMARY"], encoding="utf-8", mode="a",\
|
||||
); \
|
||||
atexit.register(gh_summary_fd.close); \
|
||||
cov = coverage.Coverage(); \
|
||||
cov.load(); \
|
||||
cov.report(file=gh_summary_fd, output_format="markdown")'
|
||||
{envpython} \
|
||||
{[python-cli-options]byte-errors} \
|
||||
{[python-cli-options]max-isolation} \
|
||||
{[python-cli-options]warnings-to-errors} \
|
||||
-c \
|
||||
'import os, pathlib, sys; \
|
||||
os.getenv("GITHUB_ACTIONS") == "true" or sys.exit(); \
|
||||
cov_report_arg_prefix = "--cov-report=xml:"; \
|
||||
test_report_arg_prefix = "--junitxml="; \
|
||||
cov_reports = [\
|
||||
arg[len(cov_report_arg_prefix):] for arg in sys.argv \
|
||||
if arg.startswith(cov_report_arg_prefix)\
|
||||
]; \
|
||||
test_reports = [\
|
||||
arg[len(test_report_arg_prefix):] for arg in sys.argv \
|
||||
if arg.startswith(test_report_arg_prefix)\
|
||||
]; \
|
||||
cov_report_file = cov_reports[-1] if cov_reports else None; \
|
||||
test_report_file = test_reports[-1] if test_reports else None; \
|
||||
gh_output_fd = open(\
|
||||
os.environ["GITHUB_OUTPUT"], encoding="utf-8", mode="a",\
|
||||
); \
|
||||
cov_report_file and \
|
||||
print(f"cov-report-files={cov_report_file !s}", file=gh_output_fd); \
|
||||
test_report_file and \
|
||||
print(f"test-result-files={test_report_file !s}", file=gh_output_fd); \
|
||||
print("codecov-flags=pytest", file=gh_output_fd); \
|
||||
gh_output_fd.close()' \
|
||||
{posargs}
|
||||
# Print out the output coverage dir and a way to serve html:
|
||||
{envpython} \
|
||||
{[python-cli-options]byte-errors} \
|
||||
{[python-cli-options]max-isolation} \
|
||||
{[python-cli-options]warnings-to-errors} \
|
||||
-c\
|
||||
'import pathlib, shlex, sys; \
|
||||
cov_html_report_arg_prefix = "--cov-report=html:"; \
|
||||
cov_html_reports = [\
|
||||
arg[len(cov_html_report_arg_prefix):] for arg in sys.argv \
|
||||
if arg.startswith(cov_html_report_arg_prefix)\
|
||||
]; \
|
||||
cov_html_reports or sys.exit(); \
|
||||
cov_html_report_dir = pathlib.Path(cov_html_reports[-1]); \
|
||||
index_file = cov_html_report_dir / "index.html";\
|
||||
index_file.exists() or sys.exit(); \
|
||||
html_url = f"file://\{index_file\}";\
|
||||
browse_cmd = shlex.join(("python3", "-Im", "webbrowser", html_url)); \
|
||||
serve_cmd = shlex.join((\
|
||||
"python3", "-Im", "http.server", \
|
||||
"--directory", str(cov_html_report_dir), "0", \
|
||||
)); \
|
||||
print(f"\nTo open the HTML coverage report, run\n\n\
|
||||
\t\{browse_cmd !s\}\n");\
|
||||
print(f"To serve \
|
||||
the HTML coverage report with a local web server, use\n\n\
|
||||
\t\{serve_cmd !s\}\n")' \
|
||||
{posargs:--cov-report=html:{envtmpdir}{/}htmlcov{/}}
|
||||
package = editable
|
||||
pass_env =
|
||||
CI
|
||||
GITHUB_*
|
||||
SSH_AUTH_SOCK
|
||||
TERM
|
||||
set_env =
|
||||
COVERAGE_PROCESS_START = {toxinidir}{/}.coveragerc
|
||||
wheel_build_env = .pkg
|
||||
Reference in New Issue
Block a user