velvet-rope / tests /test_transcript_replays.py
melomba2's picture
test: harden validator playtest coverage
86a251f
Raw
History Blame Contribute Delete
1.83 kB
import json
from pathlib import Path
import pytest
from velvet_rope.game import GameService
from velvet_rope.model_backends import DeterministicMarloweBackend
from velvet_rope.state import GameStatus, Mood
REPLAYS_FIXTURE_PATH = Path(__file__).parent / "fixtures" / "transcript_replays.json"
def load_replays():
return json.loads(REPLAYS_FIXTURE_PATH.read_text())["replays"]
REPLAYS = load_replays()
def assert_score_bounds(scores, expected_bounds):
if "rapport_min" in expected_bounds:
assert scores.rapport >= expected_bounds["rapport_min"]
if "suspicion_max" in expected_bounds:
assert scores.suspicion <= expected_bounds["suspicion_max"]
if "patience_min" in expected_bounds:
assert scores.patience >= expected_bounds["patience_min"]
if "softspot_progress" in expected_bounds:
assert scores.softspot_progress == expected_bounds["softspot_progress"]
@pytest.mark.parametrize("replay", REPLAYS, ids=lambda replay: replay["id"])
def test_deterministic_transcript_replay(replay):
service = GameService(backend=DeterministicMarloweBackend())
state = service.new_game()
mood_path = []
for line in replay["player_lines"]:
state = service.play_turn(state, line)
mood_path.append(state.mood.value)
assert state.status is GameStatus(replay["expect"]["final_status"])
assert state.mood is Mood(replay["expect"]["final_mood"])
assert state.used_tactics == set(replay["expect"]["used_tactics"])
assert_score_bounds(state.scores, replay["expect"].get("score_bounds", {}))
if "mood_path" in replay["expect"]:
assert mood_path == replay["expect"]["mood_path"]
if "assistant_reply_contains" in replay["expect"]:
assert replay["expect"]["assistant_reply_contains"].lower() in state.history[-1].content.lower()