"""Unit tests for BESS capacity degradation model.""" import pytest from remodel_engine.generation.bess_state import simulate_bess_capacity from remodel_engine.schemas.generation import BessConfig BASE_CFG = BessConfig( capacity_mwh=500.0, power_mw=125.0, rte=0.85, design_cycles=6000.0, eol_soh=0.70, ) def test_output_length() -> None: cycles = [365.0 * (i + 1) for i in range(25)] result = simulate_bess_capacity(BASE_CFG, cycles) assert len(result) == 25 def test_index_is_1_to_25() -> None: cycles = [365.0 * (i + 1) for i in range(25)] result = simulate_bess_capacity(BASE_CFG, cycles) assert list(result.index) == list(range(1, 26)) def test_capacity_decreases_with_cycles() -> None: cycles = [365.0 * (i + 1) for i in range(25)] result = simulate_bess_capacity(BASE_CFG, cycles) assert all(result.iloc[i] >= result.iloc[i + 1] for i in range(24)) def test_zero_cycles_gives_full_capacity() -> None: """Zero cumulative cycles → SOH = 1.0 → usable = nameplate.""" result = simulate_bess_capacity(BASE_CFG, [0.0] * 25) assert all(abs(v - BASE_CFG.capacity_mwh) < 1e-9 for v in result) def test_soh_floor_at_eol() -> None: """Very high cycle count should floor at eol_soh * nameplate.""" extreme_cycles = [100_000.0] * 25 result = simulate_bess_capacity(BASE_CFG, extreme_cycles) floor = BASE_CFG.capacity_mwh * BASE_CFG.eol_soh assert all(abs(v - floor) < 1e-9 for v in result) def test_augmentation_increases_capacity() -> None: cfg = BessConfig( capacity_mwh=500.0, power_mw=125.0, augmentation_schedule=[(10, 200.0)], ) cycles = [0.0] * 25 result = simulate_bess_capacity(cfg, cycles) assert result.iloc[9] > result.iloc[8] # year 10 > year 9 def test_wrong_cycles_length_raises() -> None: with pytest.raises(ValueError, match="25 entries"): simulate_bess_capacity(BASE_CFG, [365.0] * 10)