test enhancements

This commit is contained in:
John Lancaster
2026-06-23 20:08:02 -05:00
parent 4040332e8f
commit 0030c521d3
+85 -31
View File
@@ -328,7 +328,7 @@ REQ-3 lists six states: `upload`, `queued`, `processing`, `transcribed`, `failed
MVP uses SQLite with auto-create-tables at startup.
PostgreSQL migration is a post-MVP configuration change.
"""
import contextlib
from collections.abc import Generator
from sqlmodel import Session, SQLModel, create_engine
@@ -356,7 +356,8 @@ def create_all() -> None:
SQLModel.metadata.create_all(engine)
def get_session() -> Generator[Session, None, None]:
@contextlib.contextmanager
def get_session() -> Generator[Session]:
"""Yield a database session and ensure cleanup."""
with Session(engine) as session:
yield session
@@ -370,6 +371,54 @@ def get_session() -> Generator[Session, None, None]:
## 5. Test Plan
### Pytest Hierarchy Rules (Applied)
Use the following structure consistently across Step 1 tests:
- Module names: `test_*.py`
- Class names: `Test*` (group related scenarios)
- Method names: `test_<expected_outcome>` (keep them short and behavior-focused)
- Shared fixtures: nearest `conftest.py` at needed scope
Hierarchy pattern used in this step:
```text
tests/
conftest.py
test_config.py
TestSettingsLoading
test_loads_from_env
test_requires_api_key
TestProviderSettings
test_defaults_to_openrouter
test_rejects_invalid_value
test_optional_fields_default_to_none
TestPathSettings
test_path_fields_are_path_objects
test_models.py
TestDocumentModel
test_can_be_persisted
test_defaults_are_populated
TestJobModel
test_can_be_created_for_document
test_defaults_are_populated
test_transitions_to_transcribed
test_transitions_to_failed
TestTranscriptModel
test_success_record_persists
test_failure_record_persists
test_job_id_is_unique
TestRelationships
test_document_exposes_jobs
test_job_exposes_transcript
test_db.py
TestSchemaBootstrap
test_create_all_creates_expected_tables
TestSessionFactory
test_get_session_yields_session
test_session_is_closed_after_generator_exit
```
### `tests/conftest.py` — Shared Fixtures
```python tests/conftest.py
@@ -395,40 +444,45 @@ def session():
yield session
```
### `tests/test_config.py` — Configuration Tests
### `tests/test_config.py` — Configuration Hierarchy
| Test | What It Verifies |
|------|------------------|
| `test_settings_loads_from_env` | `Settings` constructs successfully when `PROVIDER_API_KEY` is set via env var |
| `test_settings_requires_api_key` | `Settings()` raises `ValidationError` when `PROVIDER_API_KEY` is missing |
| `test_provider_defaults_to_openrouter` | Default provider is `openrouter` when not explicitly set |
| `test_provider_rejects_invalid_value` | Setting `PROVIDER=invalid` raises `ValidationError` |
| `test_optional_fields_default_to_none` | `provider_model` and `provider_base_url` are `None` when unset |
| `test_path_fields_are_path_objects` | `upload_dir` and `prompt_dir` are `Path` instances |
| Class | Method | What It Verifies |
|------|--------|------------------|
| `TestSettingsLoading` | `test_loads_from_env` | `Settings` constructs successfully when `PROVIDER_API_KEY` is set via env var |
| `TestSettingsLoading` | `test_requires_api_key` | `Settings()` raises `ValidationError` when `PROVIDER_API_KEY` is missing |
| `TestProviderSettings` | `test_defaults_to_openrouter` | Default provider is `openrouter` when not explicitly set |
| `TestProviderSettings` | `test_rejects_invalid_value` | Setting `PROVIDER=invalid` raises `ValidationError` |
| `TestProviderSettings` | `test_optional_fields_default_to_none` | `provider_model` and `provider_base_url` are `None` when unset |
| `TestPathSettings` | `test_path_fields_are_path_objects` | `upload_dir` and `prompt_dir` are `Path` instances |
### `tests/test_models.py` — Model & Relationship Tests
### `tests/test_models.py` — Model & Relationship Hierarchy
| Test | What It Verifies |
|------|------------------|
| `test_create_document` | A `Document` can be persisted and read back with correct fields |
| `test_document_defaults` | `id` is auto-generated UUID, `uploaded_at` is populated |
| `test_create_job_with_document` | A `Job` linked to a `Document` via FK persists correctly |
| `test_job_defaults` | Default status is `queued`, `created_at` and `updated_at` are populated |
| `test_job_status_transitions` | Status can be updated from `queued` → `processing` → `transcribed` |
| `test_job_status_to_failed` | Status can be updated from `processing` → `failed` |
| `test_create_transcript_success` | A `Transcript` with `text` set and `error_detail=None` persists correctly |
| `test_create_transcript_failure` | A `Transcript` with `text=None` and `error_detail` set persists correctly |
| `test_document_jobs_relationship` | `document.jobs` returns the linked `Job` list |
| `test_job_transcript_relationship` | `job.transcript` returns the linked `Transcript` |
| `test_transcript_job_id_unique` | Inserting two transcripts with the same `job_id` raises an integrity error |
| Class | Method | What It Verifies |
|------|--------|------------------|
| `TestDocumentModel` | `test_can_be_persisted` | A `Document` can be persisted and read back with correct fields |
| `TestDocumentModel` | `test_defaults_are_populated` | `id` is auto-generated UUID, `uploaded_at` is populated |
| `TestJobModel` | `test_can_be_created_for_document` | A `Job` linked to a `Document` via FK persists correctly |
| `TestJobModel` | `test_defaults_are_populated` | Default status is `queued`, `created_at` and `updated_at` are populated |
| `TestJobModel` | `test_transitions_to_transcribed` | Status can be updated from `queued` → `processing` → `transcribed` |
| `TestJobModel` | `test_transitions_to_failed` | Status can be updated from `processing` → `failed` |
| `TestTranscriptModel` | `test_success_record_persists` | A `Transcript` with `text` set and `error_detail=None` persists correctly |
| `TestTranscriptModel` | `test_failure_record_persists` | A `Transcript` with `text=None` and `error_detail` set persists correctly |
| `TestRelationships` | `test_document_exposes_jobs` | `document.jobs` returns the linked `Job` list |
| `TestRelationships` | `test_job_exposes_transcript` | `job.transcript` returns the linked `Transcript` |
| `TestTranscriptModel` | `test_job_id_is_unique` | Inserting two transcripts with the same `job_id` raises an integrity error |
### `tests/test_db.py` — Database Bootstrap Tests
### `tests/test_db.py` — Database Bootstrap Hierarchy
| Test | What It Verifies |
|------|------------------|
| `test_create_all_creates_tables` | After `create_all()`, the expected tables (`document`, `job`, `transcript`) exist in the database |
| `test_get_session_yields_session` | `get_session()` yields a usable `Session` object |
| `test_session_cleanup_on_exit` | After the generator is exhausted, the session is closed |
| Class | Method | What It Verifies |
|------|--------|------------------|
| `TestSchemaBootstrap` | `test_create_all_creates_expected_tables` | After `create_all()`, the expected tables (`document`, `job`, `transcript`) exist in the database |
| `TestSessionFactory` | `test_get_session_yields_session` | `get_session()` yields a usable `Session` object |
| `TestSessionFactory` | `test_session_is_closed_after_generator_exit` | After the generator is exhausted, the session is closed |
### Marker Strategy (Step 1)
- Keep all Step 1 tests as default unit-level tests (no custom marker needed yet).
- When slower integration or external tests are introduced, add explicit markers (for example `integration`, `external`) and keep names unchanged.
---