EcoGrid / tests /test_environment.py
Loosebag's picture
fix: stabilize deployment, action safety, and benchmark reproducibility
30bdd62
Raw
History Blame Contribute Delete
3.46 kB
import pytest
import numpy as np
from env.environment import EcoGridEnv
from models.schemas import GridAction
def test_environment_initialization():
env = EcoGridEnv()
assert env.is_done is True # Before reset
assert env._state is None
def test_environment_reset():
env = EcoGridEnv()
state = env.reset(task="easy", seed=42)
assert state is not None
assert state.time_step == 0
assert 0 <= state.demand <= 200
assert 0 <= state.solar_capacity <= 1
assert 0 <= state.wind_capacity <= 1
assert env.is_done is False
assert env.current_step == 0
def test_environment_step():
env = EcoGridEnv()
env.reset(task="easy", seed=42)
action = GridAction(renewable_ratio=0.5, fossil_ratio=0.5, battery_action=0.0)
result = env.step(action)
assert result.observation.time_step == 1
assert 0 <= result.reward <= 1
assert result.done is False
assert "reward_breakdown" in result.info
assert env.current_step == 1
def test_determinism():
env1 = EcoGridEnv()
state1 = env1.reset(task="medium", seed=100)
env2 = EcoGridEnv()
state2 = env2.reset(task="medium", seed=100)
assert state1.model_dump() == state2.model_dump()
action = GridAction(renewable_ratio=0.8, fossil_ratio=0.2, battery_action=1.0)
res1 = env1.step(action)
res2 = env2.step(action)
assert res1.observation.model_dump() == res2.observation.model_dump()
assert res1.reward == res2.reward
def test_episode_termination():
env = EcoGridEnv()
env.reset(task="easy", seed=42) # easy is 48 steps
action = GridAction(renewable_ratio=0.5, fossil_ratio=0.5, battery_action=0.0)
for _ in range(47):
result = env.step(action)
assert result.done is False
result = env.step(action) # Step 48
assert result.done is True
assert result.info["termination_reason"] == "episode_complete"
def test_carbon_overrun_termination():
env = EcoGridEnv()
# hard task is carbon_strict
state = env.reset(task="hard", seed=42)
# Force high emissions to blow the budget quickly
action = GridAction(renewable_ratio=0.0, fossil_ratio=1.0, battery_action=0.0)
done = False
for _ in range(96):
result = env.step(action)
if result.done:
done = True
assert result.info["termination_reason"] == "carbon_budget_exceeded"
break
assert done is True
def test_step_accepts_dict_action_and_adds_warning_for_invalid_payload():
env = EcoGridEnv()
env.reset(task="medium", seed=42)
# Invalid dict payload should be coerced to safe fallback action
result = env.step({"renewable_ratio": "bad_value"})
assert result.done is False
assert "action_warning" in result.info
assert result.observation.time_step == 1
def test_full_episode_reproducibility_same_seed_same_trajectory():
env1 = EcoGridEnv()
env2 = EcoGridEnv()
env1.reset(task="hard", seed=123)
env2.reset(task="hard", seed=123)
action = GridAction(renewable_ratio=0.6, fossil_ratio=0.3, battery_action=0.0)
rewards_1 = []
rewards_2 = []
for _ in range(10):
r1 = env1.step(action)
r2 = env2.step(action)
rewards_1.append(r1.reward)
rewards_2.append(r2.reward)
assert r1.observation.model_dump() == r2.observation.model_dump()
assert rewards_1 == rewards_2