Testing¶
The test suite lives in tests/ (462 tests across 29 modules) using pytest and pytest-qt.
Running Tests¶
Headless Linux¶
CI runs Linux tests with offscreen Qt and xvfb:
Required system packages on Ubuntu (see .github/workflows/ci.yml):
xvfb,libxkbcommon-x11-0,libxcb-cursor0, and related XCB libraries
macOS and Windows run uv run pytest directly without xvfb.
Test Categories¶
Golden Command Tests¶
Verify that form state produces the expected CommandPlan argv and env for each tab. Fixtures live in tests/fixtures/command_states/.
Example pattern:
def test_golden_upload_folder(gui):
gui.toggle_advanced(False)
gui.inputs["upload-folder"]["path"].setText("/photos")
plan = gui.build_plan(dry_run=False)
assert _norm_argv(plan.argv) == _norm_argv([...])
assert plan.env.get("IMMICH_GO_UPLOAD_API_KEY") == "test-key"
assert not any("--api-key" in p for p in plan.argv)
Key assertions:
- Correct command tokens for the tab
- Secrets in env, not argv
- Serverless tabs omit server flags
Cross-Platform Path Normalization¶
All argv comparisons MUST use _norm_argv():
def _norm_argv(argv):
# Strips Windows drive letters (C:, D:)
# Normalizes backslashes to forward slashes
...
This ensures tests pass on Linux, macOS, and Windows CI runners.
Headless Terminal Mocks¶
Launcher tests mock platform and terminal detection:
with patch("sys.platform", "linux"):
with patch("shutil.which", return_value="/usr/bin/gnome-terminal"):
result = launch_external_terminal(...)
This prevents CI failures when no terminal emulator is installed.
CLI Contract Tests¶
core/cli_contract.py compares:
TAB_ALLOWED_FLAGSagainst captured CLI help fixtures- Live binary
--helpoutput (when binary present)
Fixtures are stored in core/fixtures/cli_help/{version}/ (bundled at runtime; also used by tests).
Fixtures¶
| Directory | Contents |
|---|---|
core/fixtures/cli_help/ |
Captured --help text per immich-go version (runtime + tests) |
tests/fixtures/command_states/ |
Golden JSON form states per tab |
Regenerating CLI Help Fixtures¶
When immich-go releases a new version:
- Install or download the new binary to
~/.immich-go-gui/bin/{version}/ - Run the capture script:
- Update
core/flags.tomlif flags changed - Run tests and fix any golden fixture drift
See Scripts for script details.
Writing New Tests¶
- Use the
guipytest fixture (pytest-qt) for widget interaction - Call
gui.build_plan()rather than clicking Run (avoids subprocess) - Always
_norm_argv()when comparing paths in argv - Mock network, subprocess, and keyring for unit tests
- Use
pyfakefsfor filesystem tests where applicable
Pre-commit¶
Local lint/format checks via pre-commit:
Configured in .pre-commit-config.yaml: trailing whitespace, YAML check, Ruff lint/format, and ty type checking of core/.
CI Matrix¶
| Workflow | Trigger | Platforms |
|---|---|---|
ci.yml |
Push to master |
ubuntu-22.04, macos-latest, windows-latest |
pr-fast-feedback.yml |
PR to master |
Same + Nuitka smoke build, CodeQL |
See CI/CD and Releases.