Spaces:
Sleeping
Sleeping
| """Tests for the text environment interface.""" | |
| import json | |
| from pathlib import Path | |
| import pytest | |
| from turnabout.envs.text_env import TextCourtEnv | |
| CASES_DIR = Path(__file__).parent.parent / "turnabout" / "cases" | |
| def case_path(): | |
| p = CASES_DIR / "stolen_prototype.json" | |
| if not p.exists(): | |
| pytest.skip("stolen_prototype.json not yet created") | |
| return str(p) | |
| class TestTextEnvEasy: | |
| def test_reset(self, case_path): | |
| env = TextCourtEnv(case_path=case_path, difficulty="easy") | |
| obs = env.reset() | |
| assert "COURT" in obs or "TESTIMONY" in obs | |
| def test_system_prompt(self, case_path): | |
| env = TextCourtEnv(case_path=case_path, difficulty="easy") | |
| prompt = env.system_prompt | |
| assert "defense attorney" in prompt | |
| assert "press" in prompt | |
| def test_step_returns_4_tuple(self, case_path): | |
| env = TextCourtEnv(case_path=case_path, difficulty="easy") | |
| env.reset() | |
| obs, reward, done, info = env.step("next") | |
| assert isinstance(obs, str) | |
| assert isinstance(reward, float) | |
| assert isinstance(done, bool) | |
| assert isinstance(info, dict) | |
| assert "valid_actions" in info | |
| def test_invalid_action(self, case_path): | |
| env = TextCourtEnv(case_path=case_path, difficulty="easy") | |
| env.reset() | |
| obs, reward, done, info = env.step("fly to the moon") | |
| assert "parse" in info.get("parse_error", "").lower() or "parse_error" in info | |
| assert reward < 0 | |
| def test_full_easy_win(self, case_path): | |
| env = TextCourtEnv(case_path=case_path, difficulty="easy") | |
| env.reset() | |
| actions = [ | |
| "next", | |
| "present patrol_schedule", | |
| "next", | |
| "next", | |
| "press revised_2", | |
| "next", | |
| "present cloning_device", | |
| "next", | |
| "present alex_alibi", | |
| ] | |
| done = False | |
| for action in actions: | |
| obs, reward, done, info = env.step(action) | |
| if done: | |
| break | |
| assert done | |
| assert "NOT GUILTY" in obs | |
| metrics = env.get_metrics() | |
| assert metrics.won | |
| assert metrics.contradiction_accuracy == 1.0 | |
| def test_max_steps(self, case_path): | |
| env = TextCourtEnv(case_path=case_path, difficulty="easy", max_steps=3) | |
| env.reset() | |
| for _ in range(5): | |
| obs, reward, done, info = env.step("next") | |
| if done: | |
| break | |
| assert done | |
| class TestTextEnvHard: | |
| def test_reset_investigation(self, case_path): | |
| env = TextCourtEnv(case_path=case_path, difficulty="hard") | |
| obs = env.reset() | |
| assert "INVESTIGATION" in obs | |
| def test_investigate_then_court(self, case_path): | |
| env = TextCourtEnv(case_path=case_path, difficulty="hard") | |
| env.reset() | |
| investigation_actions = [ | |
| "talk alex_park", | |
| "move lab", | |
| "move security_office", | |
| "examine filing_cabinet", | |
| "examine monitor_desk", | |
| "move lab", | |
| "present security_footage to chen", | |
| "move main_hallway", | |
| "move hale_office", | |
| "examine hale_desk", | |
| "go to court", | |
| ] | |
| for action in investigation_actions: | |
| obs, reward, done, info = env.step(action) | |
| assert not done, f"Game ended unexpectedly after '{action}': {obs}" | |
| assert "COURT" in obs | |
| court_actions = [ | |
| "next", | |
| "present patrol_schedule", | |
| "next", | |
| "next", | |
| "press revised_2", | |
| "next", | |
| "present cloning_device", | |
| "next", | |
| "present alex_alibi", | |
| ] | |
| for action in court_actions: | |
| obs, reward, done, info = env.step(action) | |
| if done: | |
| break | |
| assert done | |
| assert "NOT GUILTY" in obs | |