generated from john/python-template
test enhancements
This commit is contained in:
+85
-31
@@ -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.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user