Files
pvemanager/backend/tests/README.md
markmorado 89d70654fc fix(reinstall): use OSTemplate.vmid (not template_vmid) and convert memory bytes->MB
- AttributeError: OSTemplate has no 'template_vmid' field; the actual column is 'vmid'.
- Use OSTemplate.get_vmid_for_node() to support cross-node replicated templates,
  falling back to source_node/vmid otherwise.
- VMInstance.memory is stored in bytes, but Proxmox config expects MB.
2026-04-29 23:48:48 +02:00

88 lines
2.8 KiB
Markdown

# Backend Tests
Smoke / unit tests for the FastAPI backend, focused on the security-critical
modules: `app.crypto`, `app.auth`, `app.rbac`.
## Layout
```
backend/
├── pytest.ini # pytest config (testpaths=tests, markers, addopts)
├── requirements-dev.txt # test deps (-r requirements.txt + pytest …)
└── tests/
├── conftest.py # env setup + reusable fixtures
├── test_crypto.py # Fernet field-encryption helpers
├── test_auth.py # password hashing, JWT, IP parsing, perm helpers
└── test_rbac.py # PermissionEngine + registry
```
## How `conftest.py` keeps tests hermetic
The application reads configuration at import time:
- `app.config.Settings` is a `pydantic-settings` model that auto-loads `.env`
from the current working directory.
- `app.db` constructs the SQLAlchemy engine on import.
`tests/conftest.py` therefore, **before any `app.*` import**:
1. Sets `DATABASE_URL`, `SECRET_KEY`, `ADMIN_PASSWORD`, `LOG_LEVEL` to safe
test values via `os.environ.setdefault`.
2. Generates a fresh `FERNET_KEY` so encrypt/decrypt round-trips succeed.
3. Adds `backend/` to `sys.path`.
4. `chdir`s to a temp directory so the developer's local `.env` (which contains
keys not declared on `Settings`) is **not** picked up. Without this step
pydantic raises `extra_forbidden`.
No real Postgres connection is opened — SQLAlchemy connects lazily, and these
tests never issue a query.
## Running locally
There is no system-wide Python on this host, so use the same Python image as CI:
```bash
docker run --rm -v "$PWD/backend:/app" -w /app python:3.12-slim bash -c '
pip install -r requirements-dev.txt &&
python -m pytest -p no:warnings
'
```
Run a single test:
```bash
python -m pytest tests/test_auth.py::TestJWT -v
```
## CI
GitHub Actions runs the suite on every push / PR to `main` that touches
`backend/**` — see [.github/workflows/backend-tests.yml](../.github/workflows/backend-tests.yml).
Coverage is reported to the job log and uploaded as an artifact.
## Adding more tests
- **Pure / domain logic** (no DB): use the `fake_user_factory` /
`fake_role_factory` fixtures in `conftest.py`. They produce
`SimpleNamespace` objects that satisfy duck-typed access in `auth.py` and
`rbac/engine.py`.
- **Touches the DB**: build out a SQLite-backed fixture (override
`app.db.engine` with `sqlite:///:memory:` and `Base.metadata.create_all`).
Not required for the current smoke layer.
- **API endpoints**: spin up `TestClient(app)` once `get_db` and any external
Proxmox / SSH dependencies are dependency-overridden.
## Markers
Defined in `pytest.ini`:
- `@pytest.mark.smoke` — quickest sanity checks.
- `@pytest.mark.unit` — pure unit tests.
- `@pytest.mark.integration` — multi-module integration.
Run only smoke tests:
```bash
python -m pytest -m smoke
```