Skip to content

Testing

Test stack

  • pytest
  • httpx
  • FastAPI TestClient
  • proxmox-sdk (mock testing)

Test dependencies are defined in pyproject.toml under [project.optional-dependencies] -> test.

Install them with:

uv sync --extra test --group dev

Run tests

pytest

For the schema-generation and typed helper path specifically:

pytest tests/test_pydantic_generator_models.py tests/test_session_and_helpers.py

For the current route and docs contract surface:

pytest tests/test_generated_proxmox_routes.py tests/test_proxmox_codegen_docs.py tests/test_api_routes.py tests/test_stub_routes.py tests/test_admin_logs.py

Rust reconciliation tests

The optional Rust reconciliation package lives in proxbox-reconcile-rs/. Python remains the default engine, so the normal test suite must pass without the native package.

Run the Python fixture contracts and skip Rust parity when the native package is absent:

uv run pytest tests/reconciliation

Run Rust unit tests without the PyO3 extension-module link mode:

cd proxbox-reconcile-rs
cargo test --no-default-features

Install the local native package into the root uv environment:

uv pip install -e proxbox-reconcile-rs

Run strict compare-mode parity:

PROXBOX_RECONCILIATION_ENGINE=compare \
PROXBOX_RECONCILIATION_COMPARE_STRICT=true \
uv run pytest tests/reconciliation

Run explicit Rust-engine tests:

PROXBOX_RECONCILIATION_ENGINE=rust uv run pytest tests/reconciliation

Run the synthetic benchmark harness:

uv run python benchmarks/reconciliation/bench_vm_queue.py --sizes 100 1000 10000
uv run python benchmarks/reconciliation/bench_vm_queue.py --sizes 10000 --pathological

If compare mode reports mismatches, keep PROXBOX_RECONCILIATION_ENGINE=python in production and inspect proxbox_reconcile_mismatch_total through /cache/metrics or /cache/metrics/prometheus.

For the v0.0.11 surface specifically (HA routes, operational verbs, the allow_writes gate, and supporting helpers):

pytest \
  tests/test_proxmox_ha_routes.py \
  tests/test_proxmox_actions_gate.py \
  tests/test_proxmox_actions_start.py \
  tests/test_proxmox_actions_stop.py \
  tests/test_proxmox_actions_snapshot.py \
  tests/test_proxmox_actions_migrate_verb.py \
  tests/test_verb_dispatch_helpers.py \
  tests/test_sync_active.py \
  tests/test_name_collision.py \
  tests/test_vm_cloudinit_mapping.py \
  tests/test_description_metadata.py

Proxmox Mock Testing

All tests use proxmox-sdk mock features to validate Proxmox API integration. The test suite supports three mock modes:

Three Mock Modes

Mode Fixture Port Speed Use Case
MockBackend proxmox_mock_backend N/A Fastest Development iteration
HTTP Published proxmox_mock_http_published 8006 Fast User experience validation
HTTP Local proxmox_mock_http_local 8007 Fast Pre-release validation

1. In-process MockBackend (@pytest.mark.mock_backend)

The fastest mode using the proxmox_sdk.sdk.backends.mock.MockBackend. No HTTP server required.

@pytest.mark.mock_backend
async def test_vm_sync(proxmox_mock_backend):
    """Fast test using in-process MockBackend."""
    vms = await proxmox_mock_backend.request("GET", "/api2/json/nodes/pve01/qemu")

2. HTTP Published Container (@pytest.mark.mock_http)

Uses the published Docker image emersonfelipesp/proxmox-sdk:latest on port 8006.

@pytest.mark.mock_http
async def test_vm_sync_http(proxmox_mock_http_published):
    """Realistic test using HTTP container (published image)."""
    vms = await proxmox_mock_http_published.nodes.get()

3. HTTP Local Build Container (@pytest.mark.mock_http)

Uses a locally-built Docker image from ./proxmox-sdk on port 8007.

@pytest.mark.mock_http
async def test_vm_sync_http_local(proxmox_mock_http_local):
    """Realistic test using HTTP container (local build)."""
    vms = await proxmox_mock_http_local.nodes.get()

Running Tests with Docker Containers

Start both mock containers:

# Using docker compose (v2)
docker compose up -d

# Or using docker-compose (v1)
docker-compose up -d

Run the full test suite with orchestration script:

./scripts/test-with-mock.sh

Run specific test modes:

# MockBackend only (fast, no HTTP)
PROXMOX_API_MODE=mock uv run pytest tests --ignore=tests/e2e -m "mock_backend"

# HTTP published only
PROXMOX_API_MODE=mock PROXMOX_MOCK_PUBLISHED_URL=http://localhost:8006 \
  uv run pytest tests --ignore=tests/e2e -m "mock_http"

# HTTP local only
PROXMOX_API_MODE=mock PROXMOX_MOCK_LOCAL_URL=http://localhost:8007 \
  uv run pytest tests --ignore=tests/e2e -m "mock_http"

Dual Mode Testing

Tests can run against both MockBackend AND HTTP containers:

@pytest.mark.mock_backend
@pytest.mark.mock_http
async def test_vm_sync_all_modes(request, proxmox_mock_backend,
                                   proxmox_mock_http_published,
                                   proxmox_mock_http_local):
    """Test runs 3 times: backend, published HTTP, and local HTTP."""
    ...

Docker Compose Services

The docker-compose.yml defines two services:

services:
  proxmox-mock-published:
    image: emersonfelipesp/proxmox-sdk:latest
    ports:
      - "8006:8000"
    environment:
      - PROXMOX_API_MODE=mock
      - PROXMOX_MOCK_SCHEMA_VERSION=latest

  proxmox-mock-local:
    build:
      context: ./proxmox-sdk
      dockerfile: Dockerfile
    ports:
      - "8007:8000"
    environment:
      - PROXMOX_API_MODE=mock
      - PROXMOX_MOCK_SCHEMA_VERSION=latest

Both services: - Use PROXMOX_API_MODE=mock - Set PROXMOX_MOCK_SCHEMA_VERSION=latest - Have health checks enabled - Have no persistent volumes (fresh state on restart)

Environment Variables

Variable Default Description
PROXMOX_API_MODE real Set to mock for test mode
PROXMOX_MOCK_PUBLISHED_URL http://localhost:8006 Published container URL
PROXMOX_MOCK_LOCAL_URL http://localhost:8007 Local container URL
PYTEST_CURRENT_TEST auto-set Auto-detects pytest environment

pytest Markers

Marker Description
mock_backend Tests using in-process MockBackend (fast)
mock_http Tests using HTTP mock container

unit and integration are directory conventions, not pytest markers, so do not pass -m unit / -m integration.

Targeted endpoint tests

The file tests/test_endpoint_crud.py includes dedicated coverage for:

  • Proxmox endpoint CRUD lifecycle.
  • Proxmox endpoint auth validation rules.
  • NetBox endpoint singleton enforcement.

Run only this test file:

pytest tests/test_endpoint_crud.py

Compile check

python -m compileall proxbox_api
  • pytest
  • python -m compileall proxbox_api
  • mkdocs build --strict (when docs changed)
  • cargo test --no-default-features in proxbox-reconcile-rs (when Rust changes)

Generated Proxmox contract checks

When changing proxbox_api/proxmox_codegen/ or the sync-facing Proxmox service layer:

  • Regenerate proxbox_api/generated/proxmox/*/pydantic_models.py from the checked-in openapi.json artifacts.
  • Confirm array-of-object responses still emit concrete ...ResponseItem schemas.
  • Confirm helper-backed routes still return payloads compatible with existing sync code.

Troubleshooting

Container Won't Start

# Check container logs
docker compose logs proxmox-mock-published
docker compose logs proxmox-mock-local

# Verify health status
docker compose ps

# Restart containers
docker compose restart

Tests Timeout

# Increase health check timeout in docker-compose.yml
# Or wait longer before running tests:
sleep 30

Import Errors

# Ensure dependencies are installed
uv sync --frozen --extra test --group dev

# Verify imports
uv run python -c "from proxbox_api.testing import MockProxmoxContext"