Skip to content

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):

make check

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.