LiteFS Testing Strategy
Project-specific testing patterns for litefs-py and litefs-django.
When to Use
- •Writing tests for LiteFS-related code
- •Setting up test fixtures
- •Understanding test organization
Test Organization
bash
# By category pytest -m unit # Fast, no LiteFS process pytest -m integration # With Docker + FUSE pytest -m property # Property-based tests
Test Directory Structure
code
tests/ ├── unit/ # No I/O, no subprocess │ ├── domain/ # Pure domain logic (settings, config) │ ├── usecases/ # Use case tests with in-memory adapters │ └── conftest.py # In-memory adapter fixtures ├── integration/ # Requires Docker + FUSE │ ├── test_backend.py │ └── test_replication.py └── conftest.py # Shared fixtures
CI Strategy
- •Unit tests: Run on all PRs (fast, no Docker)
- •Integration tests: Run on main branch only (requires Docker + FUSE)
- •Local testing: Docker Compose setup mirrors integration CI
Test Isolation Rules
Unit tests (tests/unit/) must NOT:
- •Spawn subprocesses or call LiteFS binary
- •Access filesystem beyond temp directories
- •Require FUSE or Docker
Unit tests SHOULD use:
- •In-memory adapter fixtures:
- •
in_memory_process_runner→InMemoryProcessRunner - •
in_memory_config_writer→InMemoryConfigWriter - •
fake_primary_detector→FakePrimaryDetector
- •
In-Memory Adapter Pattern
python
# tests/unit/conftest.py
@pytest.fixture
def in_memory_process_runner():
return InMemoryProcessRunner()
# tests/unit/usecases/test_process_manager.py
def test_start_litefs(in_memory_process_runner):
manager = ProcessManager(runner=in_memory_process_runner)
manager.start()
assert in_memory_process_runner.started is True
Property-Based Testing (Hypothesis)
Use for config generation and settings validation:
bash
uv run pytest -m property -v
When to use:
| Pattern | Property to Test | Example |
|---|---|---|
| Round-trip | parse(generate(x)) == x | Config YAML generation |
| Invariants | Bounds always hold | Path validation |
| Idempotence | f(f(x)) == f(x) | Settings normalization |
python
from hypothesis import given, strategies as st
@pytest.mark.property
@given(mount_path=st.text(min_size=1).filter(lambda x: x.startswith("/")))
def test_config_includes_mount_path(mount_path):
settings = LiteFSSettings(mount_path=mount_path)
config = ConfigGenerator().generate(settings)
assert mount_path in config