4. Testing¶
Run safe local checks; CI validates platform integration separately.
Before a pull request¶
Complete setup, then run the three checks:
make pre-commit # static checks and hooks
make test-all # tests
make docs-build # strict documentation build
make check runs all three at once (and first warns if the Git hooks are missing):
test-all covers the unit/isolated skills tests, archive validation and an isolated wheel installation
that checks the installed version, entry point and bundled resources without starting the app.
It does not install dependencies or Git hooks.
Focused checks¶
| Command | Scope |
|---|---|
make check |
pre-commit-status, pre-commit, test-all and docs-build |
make test-local |
Unit and isolated skills suites; also the default pytest discovery |
make test-all |
Safe suites plus wheel/sdist checks and wheel installation |
make test-coverage |
test-all with Python coverage in reports/coverage.xml; no threshold |
make test-installation |
Build and verify archives, then smoke-check the installed wheel |
make pre-commit |
Static and docs hooks; FILES="path/a path/b" limits them to files |
make pre-commit-status |
Warn when the Git hooks are not installed |
make docs-build |
Strict documentation build |
make build-package |
Build and verify the wheel/sdist |
Use N=1 to debug the normally parallel tests (N=4). Empty test collection fails.
For a filtered run, use make test-local ARGS="-k release".
check, test-all, test-coverage and test-integration reject nonempty ARGS
or PYTEST_ADDOPTS; collection and selection filters cannot count as full validation.
Writing tests¶
Use tests/unit/test_<module>.py; tests/README.md maps the suites.
Use temporary directories, tmp_path and monkeypatch so parallel tests share no state, and
synthetic catalogs/actions for frontend tests. Release/system tests use command stubs and never publish.
Installer regressions cover failed steps and terminal/nonterminal exit status using temporary roots.
The Windows harness runs with PowerShell and fake Git/winget/Make commands; it skips if PowerShell is absent.
Startup tests stub dependency synchronization, process restart and sudo.
Coverage measures Python execution separately from subprocess, wheel and OS checks. The initial macOS/Python 3.14.8 baseline was 60% across 195 passing safe cases.
CI¶
| Suite | Environment | Boundary |
|---|---|---|
| Safe suites and wheel smoke | Ubuntu, macOS, Windows CI | POSIX deployment fixtures skip Windows |
make test-integration |
Disposable CI hosts | Linux/macOS install packages; Windows checks are read-only |
| CachyOS integration | Manual | Not covered by hosted CI |
Arch container / make act |
Explicit manual use | May mutate the execution environment |
make test-integration is for disposable CI hosts; do not run it on your workstation. Integration is serial;
empty, all-skipped, filtered, collection-only or failing runs fail. Other-platform skips are expected.
A local pass covers local checks; required platform CI jobs must also pass.
Static and documentation hooks¶
Hooks check formatting and lint (Ruff), syntax and whitespace, secrets, Markdown and spelling, the
lockfile and the strict docs build, skill links, workflow syntax (actionlint) and workflow security (zizmor). Commitizen runs only at the commit-msg stage.
make install-dev installs the Git hooks in a checkout (not in CI or Docker); run
make pre-commit-install if that step failed, and make pre-commit-status (part of make check) warns
when they are missing. make pre-commit only runs the hooks and never installs them.
See .pre-commit-config.yaml for the full list; pip-audit, bandit and markdown-link-check are disabled. .github/zizmor.yml holds the one
zizmor exception: the release workflow's checkouts keep their credentials because they push.
Configuration payload Markdown (src/personal_os_setup/config/) stays excluded from linting
because it includes templates and third-party content.