From 3d9491965f8a59f947516b4a88868492e8cdc500 Mon Sep 17 00:00:00 2001 From: Frode Helgetun Krogh <70878501+frodehk@users.noreply.github.com> Date: Tue, 7 Jan 2025 17:01:25 +0100 Subject: [PATCH] test: add test for blank fuel equinor/ecalc-internal#291 --- .../component_validation_error.py | 10 ++++ src/libecalc/presentation/yaml/model.py | 15 +++++- tests/libecalc/dto/test_fuel_consumer.py | 49 ++++++++++++++++++- 3 files changed, 70 insertions(+), 4 deletions(-) diff --git a/src/libecalc/domain/infrastructure/energy_components/component_validation_error.py b/src/libecalc/domain/infrastructure/energy_components/component_validation_error.py index 50deebe99..96e275ffb 100644 --- a/src/libecalc/domain/infrastructure/energy_components/component_validation_error.py +++ b/src/libecalc/domain/infrastructure/energy_components/component_validation_error.py @@ -51,3 +51,13 @@ def __init__(self, errors: list[ModelValidationError]): def errors(self) -> list[ModelValidationError]: return self._errors + + +class ComponentDtoValidationError(Exception): + def __init__(self, errors: list[ModelValidationError]): + self.errors = errors + messages = [str(error) for error in errors] + super().__init__("\n".join(messages)) + + def error_count(self): + return len(self.errors) diff --git a/src/libecalc/presentation/yaml/model.py b/src/libecalc/presentation/yaml/model.py index c0052bf3a..f8c27f9c6 100644 --- a/src/libecalc/presentation/yaml/model.py +++ b/src/libecalc/presentation/yaml/model.py @@ -8,6 +8,10 @@ from libecalc.application.energy.energy_model import EnergyModel from libecalc.common.time_utils import Frequency, Period from libecalc.common.variables import ExpressionEvaluator, VariablesMap +from libecalc.domain.infrastructure.energy_components.component_validation_error import ( + ComponentDtoValidationError, + ComponentValidationException, +) from libecalc.dto import ResultOptions from libecalc.dto.component_graph import ComponentGraph from libecalc.expression import Expression @@ -20,7 +24,11 @@ from libecalc.presentation.yaml.mappers.variables_mapper.get_global_time_vector import get_global_time_vector from libecalc.presentation.yaml.model_validation_exception import ModelValidationException from libecalc.presentation.yaml.resource_service import ResourceService -from libecalc.presentation.yaml.validation_errors import DtoValidationError, Location, ModelValidationError +from libecalc.presentation.yaml.validation_errors import ( + DtoValidationError, + Location, + ModelValidationError, +) from libecalc.presentation.yaml.yaml_models.exceptions import DuplicateKeyError, YamlError from libecalc.presentation.yaml.yaml_models.yaml_model import YamlValidator from libecalc.presentation.yaml.yaml_validation_context import ( @@ -104,7 +112,10 @@ def dto(self): references=self._get_reference_service(), target_period=self.period, ) - return model_mapper.from_yaml_to_dto(configuration=self._configuration) + try: + return model_mapper.from_yaml_to_dto(configuration=self._configuration) + except ComponentValidationException as e: + raise ComponentDtoValidationError(errors=e.errors()) from e @property def period(self) -> Period: diff --git a/tests/libecalc/dto/test_fuel_consumer.py b/tests/libecalc/dto/test_fuel_consumer.py index e17178125..629c6cf38 100644 --- a/tests/libecalc/dto/test_fuel_consumer.py +++ b/tests/libecalc/dto/test_fuel_consumer.py @@ -1,17 +1,26 @@ from datetime import datetime +from io import StringIO import pytest -from pydantic import ValidationError import libecalc.dto.fuel_type import libecalc.dto.types +from ecalc_cli.types import Frequency from libecalc import dto +from libecalc.application.energy_calculator import EnergyCalculator +from libecalc.common.variables import VariablesMap from libecalc.domain.infrastructure import FuelConsumer, Installation from libecalc.common.component_type import ComponentType from libecalc.common.energy_usage_type import EnergyUsageType from libecalc.common.time_utils import Period -from libecalc.domain.infrastructure.energy_components.component_validation_error import ComponentValidationException +from libecalc.domain.infrastructure.energy_components.component_validation_error import ( + ComponentValidationException, + ComponentDtoValidationError, +) from libecalc.expression import Expression +from libecalc.presentation.yaml.yaml_entities import ResourceStream +from libecalc.presentation.yaml.yaml_models.pyyaml_yaml_model import PyYamlYamlModel +from libecalc.testing.yaml_builder import YamlAssetBuilder, YamlInstallationBuilder, YamlFuelConsumerBuilder regularity = {Period(datetime(2000, 1, 1)): Expression.setup_from_expression(1)} @@ -109,3 +118,39 @@ def test_missing_fuel(self): user_defined_category="category", ) assert "Name: test\nMessage: Missing fuel for fuel consumer" in str(exc_info.value.errors()[0]) + + def test_blank_fuel_name_and_missing_fuel(self, yaml_model_factory, request): + time_vector = [datetime(2027, 1, 1), datetime(2028, 1, 1), datetime(2029, 1, 1)] + variables = VariablesMap(time_vector=time_vector, variables={}) + + fuel_consumer = YamlFuelConsumerBuilder().with_test_data().validate() + + # Setting fuel reference name to blank + fuel_consumer.fuel = "" + + installation = ( + YamlInstallationBuilder().with_name("Installation 1").with_fuel_consumers([fuel_consumer]) + ).validate() + + # No fuel is set for the asset (means None) + asset = ( + YamlAssetBuilder().with_installations([installation]).with_start(time_vector[0]).with_end(time_vector[-1]) + ).validate() + + yaml_model_factory = request.getfixturevalue("yaml_model_factory") + asset_dict = asset.model_dump( + serialize_as_any=True, + mode="json", + exclude_unset=True, + by_alias=True, + ) + + yaml_string = PyYamlYamlModel.dump_yaml(yaml_dict=asset_dict) + stream = ResourceStream(name="", stream=StringIO(yaml_string)) + + asset_yaml = yaml_model_factory(resource_stream=stream, resources={}, frequency=Frequency.YEAR) + energy_calculator = EnergyCalculator(energy_model=asset_yaml, expression_evaluator=variables) + + with pytest.raises(ComponentDtoValidationError) as exc_info: + energy_calculator.evaluate_energy_usage() + assert "Name: flare\nMessage: Missing fuel for fuel consumer" in str(exc_info.value.errors[0])