Skip to content

Commit a92071c

Browse files
authored
ci: Set up Python-focused testing infra (#742)
This patch integrates running pytest and pre-commit via tox. It includes changes needed for tracking coverage automatically for local inspection and reporting it to Codecov. This is essentially a copy of my typical boilerplate with a few more advanced hacks for communicating with GHA. It can be invoked as `tox`, `tox r`, `tox -qq`, `tox r -e pre-commit -qq -- mypy --all-files`, `tox -qq -- -vv -s tests/pytest/'tests/pytest/_cli_test.py::test_known_interrupts[ctrl-c]'` etc. `tox` itself is installable or runnable ad-hoc via `pipx` / `uvx` / `uv tool install` or one's favorite distro package manager. The Python version of where it's installed is not important. `tox` is not usually installed into regular manually-managed virtualenvs. Mentioned tools maintain internal venvs for isolating the apps and the system install would just live side-by-side with other system stuff. `tox` creates virtualenvs for its wrapped commands automatically and keeps track of cache invalidation for them. The commands wired via `tox` can either be invoked with the default arguments or with the replacement passed to tox after the `--` separator. Furthermore, the change introduces the MyPy integration into the pre-commit configuration and is set up in strict mode. This patch includes a config file for MyPy and adjusts the existing Python modules to pass the checks on every other version down to Python 3.9. Additionally, a set of basic unit tests is added to reach the bar of 100% code coverage metric, which is set as expected in the configs. Another patch included is making stderr interceptable. Previously, `sys.stderr` was exposed as a module-scoped var, while the `capsys` fixture patches the `stderr` attribute on the `sys` module. So such patching did not influence the `stderr` variable in the `_cli` module as it remained linked to the non-patched object. With this change, the ability to inspect printing to stderr is recovered and is then demonstrated in the enclosed tests. Configuration note: each underlying tool must have its configuration in a native file, it supports and *not* passed via CLI arguments in the pre-commit or tox configs. This is important because those tools may be invoked by things other than our direct automation, like editor/IDE plugins or other platforms/tools. In order for other invocations to work the same, the shared configuration must be the same. For example, if we were to disable a rule in a pylint call in pre-commit config, it wouldn't show in CI but would break in people's editors that just call pylint directly and show errors inline. ### How can we test changes Install `tox` however you like (could also optionally attempt installing `tox-uv` with it, in the same env) and run `tox`. This will execute `pytest` under your current Python interpreter. You can also try things like `tox p -qq -e py313,py39,pre-commit`, `tox r -qq -e py313,py39,pre-commit`, `tox r -qq -e pre-commit -- mypy-py313 --all-files`, `tox r -qq -e pre-commit -- mypy --all-files`.
1 parent 993b854 commit a92071c

File tree

17 files changed

+1840
-22
lines changed

17 files changed

+1840
-22
lines changed

.codecov.yml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
---
2+
3+
codecov:
4+
notify:
5+
after_n_builds: 21 # Number of test matrix+lint jobs uploading coverage
6+
wait_for_ci: false
7+
8+
require_ci_to_pass: false
9+
10+
token: >- # notsecret # repo-scoped, upload-only, stability in fork PRs
11+
7316089b-55fe-4646-b640-78d84b79d109
12+
13+
comment:
14+
require_changes: true
15+
16+
coverage:
17+
range: 100..100
18+
status:
19+
patch:
20+
default:
21+
target: 100%
22+
pytest:
23+
target: 100%
24+
flags:
25+
- pytest
26+
typing:
27+
flags:
28+
- MyPy
29+
project:
30+
default:
31+
target: 95%
32+
lib:
33+
flags:
34+
- pytest
35+
paths:
36+
- src/
37+
target: 100%
38+
tests:
39+
flags:
40+
- pytest
41+
paths:
42+
- tests/
43+
target: 100%
44+
typing:
45+
flags:
46+
- MyPy
47+
target: 90%
48+
49+
github_checks:
50+
# Annotations are deprecated in Codecov because they are misleading.
51+
# Ref: https://github.com/codecov/codecov-action/issues/1710
52+
annotations: false
53+
54+
...

.coveragerc

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
[html]
2+
show_contexts = true
3+
skip_covered = false
4+
5+
[paths]
6+
_site-packages-to-src-mapping =
7+
src
8+
*/src
9+
*\src
10+
*/lib/pypy*/site-packages
11+
*/lib/python*/site-packages
12+
*\Lib\site-packages
13+
14+
[report]
15+
skip_covered = true
16+
skip_empty = true
17+
show_missing = true
18+
exclude_also =
19+
^\s*@pytest\.mark\.xfail
20+
^\s*\.\.\.\s*(#.*)?$
21+
22+
[run]
23+
branch = true
24+
cover_pylib = false
25+
# https://coverage.rtfd.io/en/latest/contexts.html#dynamic-contexts
26+
# dynamic_context = test_function # conflicts with `pytest-cov` if set here
27+
parallel = true
28+
plugins =
29+
covdefaults
30+
relative_files = true
31+
source =
32+
.
33+
source_pkgs =
34+
pre_commit_terraform

0 commit comments

Comments
 (0)