# Testing Strategy

## Stack
- **pytest** + **pytest-asyncio** (`asyncio_mode = auto`)
- **pytest-mock** — `mocker` fixture
- **httpx** — `TestClient` for FastAPI routes
- **asgi-lifespan** — lifespan management in integration tests

## Directory layout

```
tests/
├── conftest.py              # Shared fixtures (settings override, event_loop policy)
├── conftest_factory.py      # Factories: FakeLLMBackend, FakeSessionStore, FakeMemoryStore
├── unit/                    # No external deps (mocked DB / LLM)
│   ├── core/
│   │   ├── test_events.py
│   │   ├── test_context_builder.py
│   │   ├── test_compressor.py
│   │   ├── test_registry.py
│   │   └── test_planning.py
│   ├── memory/
│   │   ├── test_store.py
│   │   └── test_extractor.py
│   ├── tools/
│   │   └── test_filesystem.py
│   ├── profiles/
│   │   └── test_base.py
│   └── config/
│       └── test_settings.py
├── integration/             # FastAPI TestClient + mocked or real DB
│   ├── test_api_routes.py
│   ├── test_websocket.py
│   └── test_memory_store.py
└── e2e/
    └── test_chat_flow.py    # Critical path: message → tool call → response
```

## Mock strategy

### LLM
`FakeLLMBackend` cycles through a list of pre-defined responses and optionally emits `ToolCallRequest` objects. This lets us test the agent loop and planning without real Ollama.

### PostgreSQL
Unit tests mock `asyncpg.Pool` via a thin `FakePool`/`FakeConnection` that stores rows in-memory (`list[dict]`). Integration tests may use a real Postgres instance via `TEST_DATABASE_URL`.

## Execution order

| Phase | Scope | Est. time |
|-------|-------|-----------|
| 1 | Infrastructure (`conftest`, `FakeLLMBackend`) + `events`, `context_builder`, `compressor`, `registry`, `profiles` | 2–3 h |
| 2 | Memory store (mock DB) + extractor | 2 h |
| 3 | API routes (`TestClient`) + WebSocket | 2 h |
| 4 | Agent loop + planning with `FakeLLMBackend` | 3 h |
| 5 | Tools (`filesystem`, `code_exec`, `terminal`) | 2 h |
| 6 | Integration with real Postgres (optional) | later |

## Running tests

```bash
# All tests
pytest

# Unit only
pytest tests/unit

# With verbose
pytest -v tests/unit/core

# Integration (requires TEST_DATABASE_URL)
TEST_DATABASE_URL=postgresql://... pytest tests/integration
```
