Spaces:
Sleeping
Sleeping
| """ | |
| tests/test_environment.py — Unit Tests for the RL Environment | |
| ============================================================== | |
| Run: pytest tests/test_environment.py -v | |
| Tests: reset(), step(), reward math, done conditions, relationship decay | |
| """ | |
| import sys | |
| import os | |
| sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) | |
| sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "server")) | |
| import pytest | |
| from server.environment import EmailTriageEnv | |
| def env(): | |
| """Fresh environment for each test.""" | |
| return EmailTriageEnv() | |
| def test_reset_returns_observation(env): | |
| obs = env.reset() | |
| assert obs.email_id >= 0 | |
| assert obs.sender != "" | |
| assert obs.time_budget_remaining == 480 | |
| def test_reset_populates_inbox(env): | |
| env.reset() | |
| state = env.state() | |
| assert len(state.inbox) == 20 # Task 1 default: 20 emails | |
| def test_reset_initializes_relationships(env): | |
| env.reset() | |
| state = env.state() | |
| assert len(state.relationships) > 0 | |
| for rel in state.relationships.values(): | |
| assert rel.health == 75.0 # All start at 75 | |
| def test_step_respond_decreases_time(env): | |
| env.reset() | |
| state_before = env.state() | |
| env.step(1) # RESPOND | |
| state_after = env.state() | |
| assert state_after.time_budget_remaining < state_before.time_budget_remaining | |
| def test_step_ignore_preserves_time(env): | |
| env.reset() | |
| state_before = env.state() | |
| env.step(0) # IGNORE | |
| state_after = env.state() | |
| assert state_after.time_budget_remaining == state_before.time_budget_remaining | |
| def test_step_respond_increases_relationship_health(env): | |
| env.reset() | |
| state_before = env.state() | |
| obs = env.state() | |
| # Find sender of first email | |
| first_email = state_before.inbox[0] | |
| sender = first_email.sender | |
| if first_email.sender_importance != "Spam": | |
| health_before = state_before.relationships[sender].health | |
| env.step(1) # RESPOND | |
| state_after = env.state() | |
| health_after = state_after.relationships[sender].health | |
| assert health_after >= health_before | |
| def test_step_ignore_vip_sets_angry(env): | |
| env.reset() | |
| state = env.state() | |
| # Find a VIP email | |
| vip_email = next((e for e in state.inbox if e.sender_importance == "VIP"), None) | |
| if vip_email is None: | |
| pytest.skip("No VIP email in this episode") | |
| # Advance to VIP email | |
| for i in range(state.inbox.index(vip_email)): | |
| env.step(1) # Skip past earlier emails | |
| # Ignore the VIP | |
| env.step(0) | |
| state_after = env.state() | |
| assert state_after.relationships[vip_email.sender].is_angry == True | |
| def test_done_when_inbox_empty(env): | |
| env.reset() | |
| state = env.state() | |
| num_emails = len(state.inbox) | |
| result = None | |
| for _ in range(num_emails): | |
| result = env.step(1) | |
| assert result.done == True | |
| def test_reward_positive_for_high_priority_respond(env): | |
| env.reset() | |
| state = env.state() | |
| # Find high-priority email | |
| high_priority = next((e for e in state.inbox if e.base_priority >= 7), None) | |
| if high_priority is None: | |
| pytest.skip("No high priority email") | |
| for i in range(state.inbox.index(high_priority)): | |
| env.step(1) | |
| result = env.step(1) # Respond to high priority | |
| assert result.reward > 0 | |
| def test_state_is_deep_copy(env): | |
| env.reset() | |
| state1 = env.state() | |
| env.step(0) | |
| state2 = env.state() | |
| # They should differ — step 0 advanced the index | |
| assert state1.current_email_index != state2.current_email_index | |