generated from john/python-template
Step 3 complete
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
"""Tests for transcription.services.transcription."""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from transcription.config import Settings
|
||||
from transcription.providers.base import ProviderError, TranscriptionResult
|
||||
from transcription.services.transcription import (
|
||||
PromptLoadError,
|
||||
TranscriptionError,
|
||||
load_image_payload,
|
||||
load_prompt_text,
|
||||
transcribe_document_image,
|
||||
)
|
||||
|
||||
|
||||
class _FakeProvider:
|
||||
def __init__(self, *, result: TranscriptionResult | None = None, error: Exception | None = None):
|
||||
self._result = result or TranscriptionResult(
|
||||
text="Transcript output",
|
||||
provider="openrouter",
|
||||
model="test-model",
|
||||
)
|
||||
self._error = error
|
||||
self.calls: list[dict[str, object]] = []
|
||||
|
||||
def transcribe(self, *, prompt_text: str, image_bytes: bytes, mime_type: str) -> TranscriptionResult:
|
||||
self.calls.append(
|
||||
{
|
||||
"prompt_text": prompt_text,
|
||||
"image_bytes": image_bytes,
|
||||
"mime_type": mime_type,
|
||||
}
|
||||
)
|
||||
if self._error:
|
||||
raise self._error
|
||||
return self._result
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
class TestPromptLoading:
|
||||
"""Verify prompt artifact loading and validation."""
|
||||
|
||||
def test_loads_prompt_text_from_prompt_dir(self, tmp_path: Path):
|
||||
"""Prompt loader returns canonical prompt text from configured prompt directory."""
|
||||
prompt_dir = tmp_path / "prompts"
|
||||
prompt_dir.mkdir()
|
||||
prompt_file = prompt_dir / "transcribe_document.md"
|
||||
prompt_file.write_text("Prompt body", encoding="utf-8")
|
||||
|
||||
settings = Settings(openrouter_api_key="test-key", prompt_dir=prompt_dir)
|
||||
text = load_prompt_text(settings=settings)
|
||||
|
||||
assert text == "Prompt body"
|
||||
|
||||
def test_missing_prompt_raises_error(self, tmp_path: Path):
|
||||
"""Prompt loader raises PromptLoadError when the file is missing."""
|
||||
prompt_dir = tmp_path / "prompts"
|
||||
prompt_dir.mkdir()
|
||||
|
||||
settings = Settings(openrouter_api_key="test-key", prompt_dir=prompt_dir)
|
||||
with pytest.raises(PromptLoadError):
|
||||
load_prompt_text(settings=settings)
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
class TestImageLoading:
|
||||
"""Verify local image payload loading and mime detection."""
|
||||
|
||||
def test_load_image_payload_reads_bytes_and_mime_type(self, tmp_path: Path):
|
||||
"""Image loader returns file bytes and a detected MIME type for supported files."""
|
||||
image_path = tmp_path / "sample.png"
|
||||
image_bytes = b"\x89PNG\r\n\x1a\n"
|
||||
image_path.write_bytes(image_bytes)
|
||||
|
||||
loaded_bytes, mime_type = load_image_payload(image_path)
|
||||
|
||||
assert loaded_bytes == image_bytes
|
||||
assert mime_type == "image/png"
|
||||
|
||||
def test_missing_image_raises_error(self, tmp_path: Path):
|
||||
"""Image loader raises TranscriptionError when image file does not exist."""
|
||||
missing = tmp_path / "missing.png"
|
||||
|
||||
with pytest.raises(TranscriptionError):
|
||||
load_image_payload(missing)
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
class TestTranscriptionService:
|
||||
"""Verify service orchestration across prompt, image, and provider calls."""
|
||||
|
||||
def test_transcribe_document_image_calls_provider_once(self, tmp_path: Path):
|
||||
"""Service loads prompt and image, then invokes provider exactly once."""
|
||||
prompt_dir = tmp_path / "prompts"
|
||||
prompt_dir.mkdir()
|
||||
(prompt_dir / "transcribe_document.md").write_text("Prompt body", encoding="utf-8")
|
||||
|
||||
image_path = tmp_path / "document.jpg"
|
||||
image_path.write_bytes(b"jpeg-bytes")
|
||||
|
||||
settings = Settings(openrouter_api_key="test-key", prompt_dir=prompt_dir)
|
||||
provider = _FakeProvider()
|
||||
|
||||
result = transcribe_document_image(image_path, settings=settings, provider=provider)
|
||||
|
||||
assert result.text == "Transcript output"
|
||||
assert len(provider.calls) == 1
|
||||
assert provider.calls[0]["prompt_text"] == "Prompt body"
|
||||
assert provider.calls[0]["image_bytes"] == b"jpeg-bytes"
|
||||
assert provider.calls[0]["mime_type"] == "image/jpeg"
|
||||
|
||||
def test_provider_error_is_wrapped(self, tmp_path: Path):
|
||||
"""Service wraps provider failures in TranscriptionError."""
|
||||
prompt_dir = tmp_path / "prompts"
|
||||
prompt_dir.mkdir()
|
||||
(prompt_dir / "transcribe_document.md").write_text("Prompt body", encoding="utf-8")
|
||||
|
||||
image_path = tmp_path / "document.png"
|
||||
image_path.write_bytes(b"png-bytes")
|
||||
|
||||
settings = Settings(openrouter_api_key="test-key", prompt_dir=prompt_dir)
|
||||
provider = _FakeProvider(error=ProviderError("upstream failure"))
|
||||
|
||||
with pytest.raises(TranscriptionError):
|
||||
transcribe_document_image(image_path, settings=settings, provider=provider)
|
||||
Reference in New Issue
Block a user