- Pydantic schemas: SolarConfig, WindConfig, BessConfig, GenerationResult - Catalog: synthetic 8760h profiles for RJ/KA/GJ solar and wind; LRU-cached loader - generation/solar.py: 25yr hourly simulation (DC losses, inverter, clipping, soiling, degradation) - generation/wind.py: power-law shear, piecewise power curve, wake/electrical losses, degradation - generation/bess_state.py: SOH-based capacity degradation with augmentation schedule - CLI: remodel --input scenario.json --output gen.parquet (Typer upgraded to 0.25.1 for Click 8.3 compat) - 43 unit tests, 97.4% coverage; mypy strict + ruff clean - S1-T10 parity gate: placeholder fixture + skipped integration tests (awaiting Nagasamudra data) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
39 lines
976 B
Python
39 lines
976 B
Python
"""Unit tests for catalog loader."""
|
|
|
|
import pytest
|
|
|
|
from remodel_engine.catalog.loader import load_solar_profile, load_wind_profile
|
|
|
|
|
|
def test_solar_shape() -> None:
|
|
arr = load_solar_profile("RJ")
|
|
assert arr.shape == (8760,)
|
|
|
|
|
|
def test_solar_normalized() -> None:
|
|
for loc in ("RJ", "KA", "GJ"):
|
|
arr = load_solar_profile(loc)
|
|
assert arr.min() >= 0.0
|
|
assert arr.max() <= 1.0 + 1e-9
|
|
|
|
|
|
def test_wind_shape() -> None:
|
|
arr = load_wind_profile("KA")
|
|
assert arr.shape == (8760,)
|
|
|
|
|
|
def test_wind_non_negative() -> None:
|
|
for loc in ("RJ", "KA", "GJ"):
|
|
arr = load_wind_profile(loc)
|
|
assert (arr >= 0).all()
|
|
|
|
|
|
def test_invalid_location_raises() -> None:
|
|
with pytest.raises(ValueError, match="Unknown location_id"):
|
|
load_solar_profile("XX")
|
|
|
|
|
|
def test_caching_returns_same_object() -> None:
|
|
a = load_solar_profile("GJ")
|
|
b = load_solar_profile("GJ")
|
|
assert a is b # lru_cache returns identical object
|