portfolio-optimiser/tests/test_backends.py
Kjell Tore Guttormsen b57aa83a30 feat(fase0): synthetic reference domain (D4) + backend profile skeleton (D2)
Completes Fase 0 (skeleton & decision-lock):

- reference_domain.py + data/reference_projects.json: a synthetic
  "anleggskostnad" portfolio (3 fictional construction-cost projects with
  cost line items) as the framework's bundled reference input. Plain typed
  loader (frozen dataclasses); the JSON-Schema data-source *contract* (B5)
  is deliberately deferred to Fase 2.
- backends.py: Profile (azure|local) + ChatBackend Protocol seam +
  AzureFoundryBackend/LocalBackend stubs + get_backend() selector
  (fail-fast on unknown profile). Empty skeleton per D2 — create_chat_client
  raises NotImplementedError until live wiring in Fase 1. Return type is the
  MAF BaseChatClient (the common base of FoundryChatClient/OpenAIChatClient).

Quality gate green: ruff format + check, mypy (src) clean, 12 pytest passed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H9FyyENxebxVThjrn9et8C
2026-06-23 22:38:41 +02:00

39 lines
1.2 KiB
Python

"""Tests for the backend profile skeleton (D2)."""
import pytest
from portfolio_optimiser.backends import (
AzureFoundryBackend,
ChatBackend,
LocalBackend,
Profile,
get_backend,
)
def test_get_backend_by_string() -> None:
assert isinstance(get_backend("azure"), AzureFoundryBackend)
assert isinstance(get_backend("local"), LocalBackend)
def test_get_backend_by_enum() -> None:
assert get_backend(Profile.AZURE).profile is Profile.AZURE
assert get_backend(Profile.LOCAL).profile is Profile.LOCAL
def test_backends_satisfy_seam() -> None:
# Structural conformance to the ChatBackend Protocol (the D2 seam).
assert isinstance(get_backend("azure"), ChatBackend)
assert isinstance(get_backend("local"), ChatBackend)
def test_unknown_profile_fails_fast() -> None:
with pytest.raises(ValueError):
get_backend("on-prem")
@pytest.mark.parametrize("profile", ["azure", "local"])
def test_create_chat_client_is_skeleton(profile: str) -> None:
# Fase 0: the seam is defined but not wired — must fail loudly, not silently.
with pytest.raises(NotImplementedError):
get_backend(profile).create_chat_client(model="dummy-model")