polyglot-tutor / tests /test_services.py
blizzarman's picture
feat: M0 walking skeleton (app, service protocols, CI/CD, Space deploy)
00d5ae5
Raw
History Blame Contribute Delete
1.94 kB
import io
import wave
from pathlib import Path
from tutor.domain.models import Attempt, CEFRLevel, Learner
from tutor.services.asr.base import FakeASRClient
from tutor.services.storage.memory import InMemoryRepository
from tutor.services.tts.base import FakeTTSClient
def test_cefr_level_ordering() -> None:
assert CEFRLevel.A1.rank == 0
assert CEFRLevel.C2.rank == 5
assert CEFRLevel.B1.distance(CEFRLevel.B2) == 1
assert CEFRLevel.A1.distance(CEFRLevel.C2) == 5
async def test_fake_tts_returns_a_valid_wav() -> None:
result = await FakeTTSClient().synthesize("Hello world", language="en")
assert result.format == "wav"
with wave.open(io.BytesIO(result.audio), "rb") as wav:
assert wav.getnchannels() == 1
assert wav.getnframes() > 0
async def test_fake_asr_transcribes() -> None:
client = FakeASRClient(text="bonjour")
transcription = await client.transcribe(Path("/tmp/whatever.wav"), language="fr")
assert transcription.text == "bonjour"
assert transcription.language == "fr"
assert client.calls == [Path("/tmp/whatever.wav")]
async def test_memory_repository_roundtrip() -> None:
repo = InMemoryRepository()
learner = Learner(display_name="Arthur", source_lang="fr", target_lang="en")
await repo.save_learner(learner)
assert await repo.get_learner(learner.id) == learner
assert await repo.get_learner("missing") is None
first = Attempt(learner_id=learner.id, exercise_id="ex1", score=0.5)
second = Attempt(learner_id=learner.id, exercise_id="ex2", score=1.0)
await repo.save_attempt(second)
await repo.save_attempt(first)
attempts = await repo.list_attempts(learner.id)
assert [a.exercise_id for a in attempts] == sorted(
[a.exercise_id for a in attempts],
key=lambda ex_id: next(a.created_at for a in attempts if a.exercise_id == ex_id),
)
assert await repo.list_attempts("missing") == []