Dev – Testing
Dmitrii Iurco edited this page 2026-06-11 15:39:28 -04:00

Status: Active | Owner: @roof | Applies to: main (2026-06) | Updated: 2026-06-11

Dev – Testing


Running tests

# Run on: your development machine, from the repo root
make test            # pytest unit tests (excludes e2e and integration)
make test-coverage   # with coverage; HTML report in htmlcov/
make test-api        # API endpoint tests only

All unit tests pass without a running stack. CI (Gitea Actions) runs the unit suite on every push.


Test layout

tests/                    Unit and API endpoint tests; no services required
tests/integration/        Require a running PIC stack
tests/e2e/                Playwright UI and WireGuard end-to-end tests

Unit tests

The unit suite covers manager classes, route handlers, and utility functions. Tests use unittest.mock / pytest-mock for all Docker SDK calls, filesystem writes, and subprocess invocations.

Important rule: when testing write-failure paths, mock builtins.open with side_effect=OSError. Do not rely on unwritable host paths — CI may run as root and can create any path.

The unit suite has approximately 3,218 tests as of mid-2026 (run make test to see the current count).

Integration tests

# Run on: your development machine, against a running make start stack
make test-integration              # full suite; modifies cell state
make test-integration-readonly     # read-only checks; safe to run at any time

These tests create peers, install services, and change configuration. Run them against a development cell, not production.

End-to-end tests

# Run on: your development machine
make test-e2e-deps    # install Playwright and browser binaries (run once)
make test-e2e-api     # API-level e2e tests
make test-e2e-ui      # Browser-level UI tests via Playwright

The Playwright tests drive a real browser against a running stack. test-e2e-ui tests include WireGuard tunnel tests that require actual WireGuard kernel support.


What to test

  • Every new API endpoint needs at least one test: happy path, auth failure (401), and the expected error case.
  • Every new manager method needs a test that mocks its external dependencies (Docker, filesystem, subprocess).
  • Do not test Flask routing boilerplate or trivial getters. Test behaviour and invariants.
  • Do not add tests for things that are covered clearly by the code itself — only add tests when the behaviour is non-obvious or the failure mode matters.

CI

Gitea Actions runs the unit suite on every push using the self-hosted runner VMs (gitea-action0 trusted, gitea-action1 sacrificial for untrusted builds). The workflow file calls:

# Run by: Gitea Actions on the gitea-action0 runner
pytest tests/ --ignore=tests/e2e --ignore=tests/integration

Image builds (for the email, calendar, and files service images) run on path-filtered pushes to the pic-services repository.


Webui tests

# Run on: your development machine, from the webui/ directory
cd webui && npm run test    # vitest unit tests

The webui unit tests cover React component logic and the Axios client wrapper. They do not require a running API.