Testing¶
Tests follow a pyramid; uv run pytest runs the fast tiers, and markers select tiers.
The pyramid¶
| Tier | Directory | What | Needs |
|---|---|---|---|
| Unit | tests/a_unit/ |
renderers, CLI/config, pure logic (schemas, net, cloud-init/XML) | nothing (runs everywhere) |
| Integration | tests/b_integration/ |
the real libvirt backend, skip-gated by capability | libvirtd, qemu-img, cloud-localds, /dev/kvm |
| End-to-end | tests/c_e2e/ |
the API through TestClient (stub) + a Docker test that runs the suite in a Linux container |
Docker for the container test |
Integration tests skip cleanly on macOS/CI without KVM; the pure renderers still cover the domain-XML and cloud-init logic on every platform.
Running¶
uv run pytest # all fast tiers
make test # alias
make lint # ruff format --check + ruff check + ty (+ pyrefly, mypy)
make test-cov # coverage report
Select by marker:
Conformance & deploy checks¶
- Conformance:
uv run python scripts/conformance.pydrives the realhcloudPython client through create → poll → list → power → delete against the stub. PrintsCONFORMANCE OK. - Deploy smoke test:
./deploy/test-in-docker.shruns the full pyinfra deploy into a throwaway systemd container and checks the API serves. It exercises everything except the actual KVM boot.
Conventions¶
flush()in DB tests; refresh objects afterwards.- The
conftest.pyenv is hermetic (backend/config/DB viaos.environ.setdefault) so tests never leak acloudalone.sqlite. - Non-trivial logic ships with a runnable check: many pure modules carry an
assert-based__main__self-check (uv run python -m cloudalone.net).