SurfSense/surfsense_backend/tests
CREDO23 3efe51e6ec refactor(agents): move filesystem_state, path_resolver, sandbox to app/agents/shared (slice 3b)
Relocate three leaf filesystem-cluster modules to the shared kernel and flip
all 38 importers. No re-export shims needed (no frozen single-agent importer).
This also resolves the pre-existing shared->new_chat back-edge from
shared/receipt_command.py onto filesystem_state.

filesystem_backends is intentionally deferred to slice 5: it depends on
new_chat middleware (kb_postgres_backend, multi_root_local_folder_backend)
that have not yet moved, so relocating it now would create a shared->new_chat edge.
2026-06-04 12:34:28 +02:00
..
e2e feat(tests): add mock response for file ownership in composio_module 2026-05-16 20:20:04 +05:30
fixtures remove stale ElectricSQL references from changelog and test fixtures 2026-03-24 17:07:11 +02:00
integration test: add agent refactor guardrail suite 2026-06-04 11:44:23 +02:00
unit refactor(agents): move filesystem_state, path_resolver, sandbox to app/agents/shared (slice 3b) 2026-06-04 12:34:28 +02:00
utils feat: implement task dispatcher for document processing 2026-02-26 23:55:47 +05:30
__init__.py feat: Add end-to-end tests for document upload pipeline and shared test utilities 2026-02-25 16:39:45 +05:30
conftest.py feat: add should_summarize parameter to task dispatchers 2026-02-26 19:12:37 -08:00
README.md test: add notifications unit tests and conventions doc 2026-06-03 21:53:06 +02:00

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 current_active_user 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

# 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