AquaGuard-RL / tests /test_models.py
Ashgen12's picture
Upload folder using huggingface_hub
7e69b8f verified
Raw
History Blame Contribute Delete
5.9 kB
# tests/test_models.py
"""Tests for AquaGuard-RL data models (Action, Observation, State)."""
import sys
import os
import pytest
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "src"))
from models import AquaGuardAction, AquaGuardState, ZoneObservation, CropObservation
class TestAquaGuardAction:
"""Tests for AquaGuardAction validation."""
def test_default_action_is_valid(self):
"""Default action should be valid."""
action = AquaGuardAction()
assert action is not None
total = sum(action.crop_allocation.values())
assert total <= 1.001
def test_allocation_sum_valid(self):
"""Valid allocation summing to exactly 1.0."""
action = AquaGuardAction(
crop_allocation={
"rice": 0.20, "wheat": 0.20, "millet": 0.20,
"pulses": 0.15, "oilseeds": 0.15, "vegetables": 0.10,
}
)
assert abs(sum(action.crop_allocation.values()) - 1.0) < 0.01
def test_allocation_sum_too_high_raises(self):
"""Allocation sum > 1.0 should raise ValueError."""
with pytest.raises(Exception): # pydantic ValidationError
AquaGuardAction(
crop_allocation={
"rice": 0.40, "wheat": 0.40, "millet": 0.30,
"pulses": 0.10, "oilseeds": 0.05, "vegetables": 0.03,
}
)
def test_negative_allocation_raises(self):
"""Negative allocation should raise ValueError."""
with pytest.raises(Exception):
AquaGuardAction(
crop_allocation={"rice": -0.1, "wheat": 0.5}
)
def test_invalid_crop_raises(self):
"""Unknown crop in allocation should raise ValueError."""
with pytest.raises(Exception):
AquaGuardAction(crop_allocation={"corn": 0.5, "rice": 0.3})
def test_water_quota_bounds(self):
"""Water quota must be in [0, 2000]."""
# Valid
action = AquaGuardAction(water_quotas={"zone_a": 0, "zone_b": 2000, "zone_c": 500})
assert action.water_quotas["zone_b"] == 2000
# Invalid
with pytest.raises(Exception):
AquaGuardAction(water_quotas={"zone_a": 2001})
def test_invalid_irrigation_method_raises(self):
"""Invalid irrigation method should raise ValueError."""
with pytest.raises(Exception):
AquaGuardAction(irrigation_methods={"zone_a": "canal"})
def test_valid_irrigation_methods(self):
"""All valid irrigation methods should be accepted."""
for method in ["flood", "sprinkler", "drip"]:
action = AquaGuardAction(
irrigation_methods={"zone_a": method, "zone_b": method, "zone_c": method}
)
assert action.irrigation_methods["zone_a"] == method
def test_extraction_limit_bounds(self):
"""Extraction limit must be in [0, 60]."""
with pytest.raises(Exception):
AquaGuardAction(extraction_limits={"zone_a": 61.0})
def test_subsidy_adjustment_bounds(self):
"""Subsidy adjustment must be in [-1, 1]."""
with pytest.raises(Exception):
AquaGuardAction(subsidy_adjustments={"rice": 1.5})
with pytest.raises(Exception):
AquaGuardAction(subsidy_adjustments={"rice": -1.5})
def test_justification_max_length(self):
"""Justification cannot exceed 2000 characters."""
# Valid: empty
action = AquaGuardAction(justification="")
assert action.justification == ""
# Valid: long
action = AquaGuardAction(justification="x" * 2000)
assert len(action.justification) == 2000
def test_partial_allocation_valid(self):
"""Allocation summing to less than 1.0 (fallow land) is valid."""
action = AquaGuardAction(
crop_allocation={"rice": 0.30, "wheat": 0.20}
)
assert sum(action.crop_allocation.values()) < 1.0
class TestAquaGuardState:
"""Tests for AquaGuardState model."""
def test_default_state_valid(self):
"""Default state should be valid."""
state = AquaGuardState()
assert state.task_name == "baseline"
assert state.max_steps == 10
assert state.cumulative_reward == 0.0
def test_state_with_episode_id(self):
"""State with explicit episode_id."""
state = AquaGuardState(episode_id="test-123", step_count=5)
assert state.episode_id == "test-123"
assert state.step_count == 5
class TestZoneObservation:
"""Tests for ZoneObservation model."""
def test_valid_zone_obs(self):
"""Valid zone observation should be created."""
zone = ZoneObservation(
zone_id="zone_a",
groundwater_depth_m=25.0,
groundwater_recharge_rate_mm_yr=180.0,
soil_fertility=0.75,
soil_salinity=0.12,
arable_land_ha=80000.0,
active_irrigation_method="flood",
water_used_mm=900.0,
is_in_danger_zone=False,
is_collapsed=False,
)
assert zone.zone_id == "zone_a"
assert zone.groundwater_depth_m == 25.0
def test_fertility_bounds(self):
"""Soil fertility must be in [0, 1]."""
with pytest.raises(Exception):
ZoneObservation(
zone_id="zone_a",
groundwater_depth_m=25.0,
groundwater_recharge_rate_mm_yr=180.0,
soil_fertility=1.5, # Invalid
soil_salinity=0.12,
arable_land_ha=80000.0,
active_irrigation_method="flood",
water_used_mm=900.0,
is_in_danger_zone=False,
)