test(integration): validate optimizer economics and document measurement settings

This commit is contained in:
Andreas
2026-09-16 12:30:03 +02:00
parent 7338baff56
commit 876756b82d
2 changed files with 28 additions and 9 deletions
+4 -1
View File
@@ -91,7 +91,10 @@ class MeasurementCommonSettings(SettingsBaseModel):
}, },
) )
household: Optional[HouseholdSettings] = None household: Optional[HouseholdSettings] = Field(
default=None,
json_schema_extra={"description": "Optional household energy balance definition.", "examples": [None]},
)
energy_context_seconds: int = Field(default=86400, gt=0, le=604800, strict=True) energy_context_seconds: int = Field(default=86400, gt=0, le=604800, strict=True)
@model_validator(mode="after") @model_validator(mode="after")
+24 -8
View File
@@ -4,6 +4,7 @@ from pathlib import Path
from typing import Any from typing import Any
from unittest.mock import patch from unittest.mock import patch
import numpy as np
import pytest import pytest
from pydantic import ValidationError from pydantic import ValidationError
from pypdf import PdfReader from pypdf import PdfReader
@@ -140,14 +141,29 @@ async def test_optimize(
f"cp {TESTDATA_FILE} {solution_file}\n" f"cp {TESTDATA_FILE} {solution_file}\n"
) )
assert genetic_solution.result.Gesamtbilanz_Euro == pytest.approx( # Keep the output contract, but do not demand an identical stochastic
expected_result.result.Gesamtbilanz_Euro # schedule or monetary golden from the previous direct-consumption model.
) assert set(genetic_solution.model_dump()) == set(expected_result.model_dump())
result = genetic_solution.result
# Assert that the output contains all expected entries. expected_slots = len(input_data.ems.pv_forecast_wh) - fixed_start_hour
# This does not assert that the optimization always gives the same result! assert len(result.grid_consumption_wh_per_hour) == expected_slots
# Reproducibility and mathematical accuracy should be tested on the level of individual components. assert len(result.grid_feed_in_wh_per_hour) == expected_slots
compare_dict(genetic_solution.model_dump(), expected_result.model_dump()) prices = np.asarray(genetic_solution.parameters.ems.electricity_price_per_wh)[fixed_start_hour:]
tariffs = genetic_solution.parameters.ems.feed_in_tariff_per_wh
if isinstance(tariffs, list):
tariffs = np.asarray(tariffs)[fixed_start_hour:]
expected_costs = np.asarray(result.grid_consumption_wh_per_hour) * prices
expected_revenues = np.asarray(result.grid_feed_in_wh_per_hour) * tariffs
np.testing.assert_allclose(result.costs_per_hour, expected_costs)
np.testing.assert_allclose(result.revenue_per_hour, expected_revenues)
assert result.total_costs == pytest.approx(sum(expected_costs))
assert result.total_revenue == pytest.approx(sum(expected_revenues))
assert result.total_balance == pytest.approx(sum(expected_costs) - sum(expected_revenues))
assert result.total_losses == pytest.approx(sum(result.losses_per_hour))
assert all(value >= 0 for value in result.grid_consumption_wh_per_hour)
assert all(value >= 0 for value in result.grid_feed_in_wh_per_hour)
assert all(0 <= value <= 100 for value in result.battery_soc_per_hour)
assert all(0 <= value <= 100 for value in result.ev_soc_per_hour)
# Check the correct generic optimization solution is created # Check the correct generic optimization solution is created
optimization_solution = await genetic_solution.optimization_solution() optimization_solution = await genetic_solution.optimization_solution()