# Testing Rules

## Coverage requirement

Every module must have a corresponding test file. No exceptions. The Django version broke in E2E because key modules had zero tests — we don't repeat that mistake.

## What to test

For each module, test:
1. **Happy path** — the normal case works
2. **Error paths** — malformed input, missing fields, invalid values
3. **Edge cases** — empty strings, None values, boundary conditions
4. **Provider differences** — OpenAI vs Anthropic response formats differ

## LLM mocking

Never call real LLM APIs in tests. Use `unittest.mock.AsyncMock` or pytest fixtures that return canned responses. Test the parsing and orchestration, not the LLM.

## Database mocking

Unit tests mock the DB layer. Integration tests use a real test database (or testcontainers). Keep these separate — unit tests must be fast (<5 seconds total).

## Diff/patch tests

The diff application code (V4A, search/replace) is pure logic with no I/O. Test it exhaustively:
- Malformed blocks, partial matches, empty input
- Multi-hunk patches, fuzzy matching at all fuzz levels
- EOF handling, context line matching
- File path extraction from markers

## Validation tests

Test every language validator with:
- Valid code (parses successfully)
- Syntax errors (returns failure, doesn't crash)
- Empty input, None input
- Unicode, unusual whitespace

## FastAPI test client

Use `httpx.AsyncClient` with `app=app` for router tests. Don't start a real server.

```python
@pytest.fixture
async def client(app):
    async with httpx.AsyncClient(transport=httpx.ASGITransport(app=app), base_url="http://test") as c:
        yield c
```
