mirror of
https://github.com/denizsafak/abogen.git
synced 2026-07-18 13:40:27 +02:00
feat: add contract test suite for Plugin API
Create reusable contract tests for TTS Plugin Architecture: - conftest.py: shared fixtures and stubs (FakeEngine, FakeSession, etc.) - test_types_contract.py: value object contracts (frozen, immutability, equality) - test_errors_contract.py: error hierarchy contracts - test_manifest_contract.py: manifest type contracts - test_engine_contract.py: Engine protocol contracts (lifecycle, dispose) - test_session_contract.py: EngineSession protocol contracts - test_capabilities_contract.py: capability protocol contracts - test_host_context_contract.py: HostContext contracts - test_plugin_contract.py: plugin contract (exports, create_engine) 124 tests covering all public API contracts.
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
"""Contract tests for HostContext.
|
||||
|
||||
These tests verify that HostContext satisfies the architectural requirements:
|
||||
- Minimal (3 fields maximum)
|
||||
- Frozen dataclass
|
||||
- config_dir: Path
|
||||
- logger: Logger
|
||||
- http_client: HttpClient protocol
|
||||
"""
|
||||
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from abogen.tts_plugin.host_context import HttpClient, HostContext
|
||||
|
||||
|
||||
class TestHostContextContract:
|
||||
"""Contract tests for HostContext dataclass."""
|
||||
|
||||
def test_is_frozen_dataclass(self) -> None:
|
||||
assert hasattr(HostContext, "__dataclass_params__")
|
||||
assert HostContext.__dataclass_params__.frozen is True
|
||||
|
||||
def test_required_fields(self, tmp_path: Path) -> None:
|
||||
logger = logging.getLogger("test")
|
||||
|
||||
class FakeClient:
|
||||
def get(self, url: str, **kwargs: object) -> object:
|
||||
return None
|
||||
|
||||
def post(self, url: str, **kwargs: object) -> object:
|
||||
return None
|
||||
|
||||
ctx = HostContext(
|
||||
config_dir=tmp_path,
|
||||
logger=logger,
|
||||
http_client=FakeClient(),
|
||||
)
|
||||
assert ctx.config_dir == tmp_path
|
||||
assert ctx.logger is logger
|
||||
|
||||
def test_immutability(self, tmp_path: Path) -> None:
|
||||
class FakeClient:
|
||||
def get(self, url: str, **kwargs: object) -> object:
|
||||
return None
|
||||
|
||||
def post(self, url: str, **kwargs: object) -> object:
|
||||
return None
|
||||
|
||||
ctx = HostContext(
|
||||
config_dir=tmp_path,
|
||||
logger=logging.getLogger("test"),
|
||||
http_client=FakeClient(),
|
||||
)
|
||||
with pytest.raises(AttributeError):
|
||||
ctx.config_dir = Path("/other") # type: ignore[misc]
|
||||
|
||||
def test_max_three_fields(self) -> None:
|
||||
"""Architecture spec: HostContext is minimal (3 fields max)."""
|
||||
import dataclasses
|
||||
|
||||
fields = dataclasses.fields(HostContext)
|
||||
assert len(fields) <= 3
|
||||
|
||||
|
||||
class TestHttpClientProtocolContract:
|
||||
"""Contract tests for HttpClient protocol."""
|
||||
|
||||
def test_http_client_is_protocol(self) -> None:
|
||||
assert hasattr(HttpClient, "__protocol_attrs__")
|
||||
|
||||
def test_http_client_has_get(self) -> None:
|
||||
assert hasattr(HttpClient, "get")
|
||||
|
||||
def test_http_client_has_post(self) -> None:
|
||||
assert hasattr(HttpClient, "post")
|
||||
|
||||
def test_http_client_satisfied(self) -> None:
|
||||
class FakeClient:
|
||||
def get(self, url: str, **kwargs: object) -> object:
|
||||
return None
|
||||
|
||||
def post(self, url: str, **kwargs: object) -> object:
|
||||
return None
|
||||
|
||||
client = FakeClient()
|
||||
assert isinstance(client, HttpClient)
|
||||
Reference in New Issue
Block a user