6ede33ccdb
Build and Push Docker Images / create_manifest (web, surfsense-web, , cpu) (push) Has been cancelled
Build and Push Docker Images / finalize_release (push) Has been cancelled
Obsidian Plugin Lint / lint (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_web, cpu, ./surfsense_web/Dockerfile, web, surfsense-web, ubuntu-24.04-arm, linux/arm64, arm64, , runner, false, cpu) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_web, cpu, ./surfsense_web/Dockerfile, web, surfsense-web, ubuntu-latest, linux/amd64, amd64, , runner, false, cpu) (push) Has been cancelled
Build and Push Docker Images / compute_version (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, cpu, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-24.04-arm, linux/arm64, arm64, , production, false, cpu) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, cpu, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-latest, linux/amd64, amd64, , production, false, cpu) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, cu126, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-24.04-arm, linux/arm64, arm64, -cuda126, production, true, cuda126) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, cu126, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-latest, linux/amd64, amd64, -cuda126, production, true, cuda126) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, cu128, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-24.04-arm, linux/arm64, arm64, -cuda, production, true, cuda) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, cu128, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-latest, linux/amd64, amd64, -cuda, production, true, cuda) (push) Has been cancelled
Build and Push Docker Images / verify_digests (push) Has been cancelled
Build and Push Docker Images / create_manifest (backend, surfsense-backend, , cpu) (push) Has been cancelled
Build and Push Docker Images / create_manifest (backend, surfsense-backend, -cuda, cuda) (push) Has been cancelled
Build and Push Docker Images / create_manifest (backend, surfsense-backend, -cuda126, cuda126) (push) Has been cancelled
63 lines
3.0 KiB
Markdown
63 lines
3.0 KiB
Markdown
# Tests
|
|
|
|
How the backend test suite is organized and the conventions to follow when adding tests.
|
|
|
|
## Layout: type-first, module-mirrored
|
|
|
|
Tests are split by **type** at the top level, and each type **mirrors the `app/` module tree** inside:
|
|
|
|
```
|
|
tests/
|
|
├── conftest.py # global fixtures + DATABASE_URL pinning
|
|
├── unit/ # pure logic: no DB, no app, no network
|
|
│ └── notifications/
|
|
│ ├── api/test_transform.py
|
|
│ └── service/
|
|
│ ├── messages/test_connector_indexing.py
|
|
│ └── test_metadata.py
|
|
└── integration/ # real PostgreSQL (pgvector)
|
|
├── conftest.py # async engine, transactional db_session, db_user, ...
|
|
└── notifications/
|
|
├── conftest.py # module-scoped fixtures (e.g. transactional client)
|
|
└── test_*_handler.py
|
|
```
|
|
|
|
To find a feature's tests, look under `tests/<type>/<same path as app/>`.
|
|
|
|
## Unit vs integration
|
|
|
|
- `@pytest.mark.unit` — pure, fast, no I/O. Test behavior through a public function's inputs/outputs.
|
|
- `@pytest.mark.integration` — requires a real database. Run with `AUTH_TYPE=LOCAL`.
|
|
|
|
Maximize logic covered by unit tests; keep integration tests for what genuinely needs the DB (persistence, SQL filters, scoping, HTTP wiring).
|
|
|
|
## Principles
|
|
|
|
- **Behavior, not implementation.** Assert observable outputs (returned values, persisted rows, HTTP responses), never private helpers. Tests should survive a refactor.
|
|
- **Functional core / imperative shell.** Put pure decision logic in a side-effect-free module (e.g. `app/notifications/service/messages/`) so it is unit-testable; keep the persistence shell thin and cover it with a few integration tests.
|
|
- **One responsibility per test file**, mirroring the slice it covers.
|
|
- **Mock only at system boundaries** (external APIs, brokers), never internal collaborators. Prefer dependency overrides and the transactional `db_session` over mocks.
|
|
|
|
## Fixtures
|
|
|
|
`conftest.py` is scoped to its directory and below. Keep truly global fixtures in `tests/conftest.py`; put module-specific fixtures in that module's `conftest.py` so a DB fixture never loads for a pure unit test.
|
|
|
|
For API integration tests, override `get_async_session` and `get_auth_context` to ride the test's transactional `db_session` (see `tests/integration/notifications/conftest.py`): rows seeded in the test and rows read via the endpoint share one transaction that rolls back automatically.
|
|
|
|
## Import mode
|
|
|
|
The suite uses `--import-mode=importlib` with `pythonpath = ["."]` (see `pyproject.toml`). This lets test files share basenames across modules (e.g. many `test_api.py`) without `__init__.py` boilerplate; new test directories do not need an `__init__.py`.
|
|
|
|
## Running
|
|
|
|
```bash
|
|
# fast unit tests
|
|
uv run pytest -m unit
|
|
|
|
# integration (needs Postgres + pgvector)
|
|
AUTH_TYPE=LOCAL uv run pytest -m integration
|
|
|
|
# a single module's tests
|
|
uv run pytest tests/unit/notifications
|
|
```
|