Skip to content

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:

uv run pytest -m unit
uv run pytest -m "not docker and not integration"

Conformance & deploy checks

  • Conformance: uv run python scripts/conformance.py drives the real hcloud Python client through create → poll → list → power → delete against the stub. Prints CONFORMANCE OK.
  • Deploy smoke test: ./deploy/test-in-docker.sh runs 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.py env is hermetic (backend/config/DB via os.environ.setdefault) so tests never leak a cloudalone.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).