From 675759f8fde26f63fcce18fe1521d6a5a21d76d1 Mon Sep 17 00:00:00 2001 From: Hatim Dinia <33469289+hdinia@users.noreply.github.com> Date: Wed, 4 Sep 2024 11:01:18 +0200 Subject: [PATCH 1/2] fix(ui): add missing `i18n` key and styles on `EmptyView` (#2127) --- webapp/src/components/common/MatrixInput/index.tsx | 2 +- webapp/src/components/common/page/SimpleContent.tsx | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/webapp/src/components/common/MatrixInput/index.tsx b/webapp/src/components/common/MatrixInput/index.tsx index c48e67d508..d035a94cce 100644 --- a/webapp/src/components/common/MatrixInput/index.tsx +++ b/webapp/src/components/common/MatrixInput/index.tsx @@ -183,7 +183,7 @@ function MatrixInput({ isPercentDisplayEnabled={enablePercentDisplay} /> ) : ( - !isLoading && + !isLoading && )} {openImportDialog && ( diff --git a/webapp/src/components/common/page/SimpleContent.tsx b/webapp/src/components/common/page/SimpleContent.tsx index 6be0cd51b0..03c8525eec 100644 --- a/webapp/src/components/common/page/SimpleContent.tsx +++ b/webapp/src/components/common/page/SimpleContent.tsx @@ -16,6 +16,7 @@ function EmptyView(props: EmptyViewProps) { Date: Wed, 4 Sep 2024 13:53:40 +0200 Subject: [PATCH 2/2] ci(test): parallel pytest execution (#2133) Enable the use of pytest-xdist to run tests in parallel, in CI or developer env. Following issues with parallel execution of tests are solved : - some checks depended on the consistency at 2 moments in time of the result of disk_usage, which was anyway not a good idea (dependent on what happens elsewhere on the machine). It's now replaced with mocking - some parameterized tests had random sort order, which is not allowed by pytest-xdist (all workers must have exactly the same tests in the same order) - the command_factory test checked something in its teardown, assuming all tests were executed in the same process, which is not the case anymore. The same check is done as a separate unit tests. Possible remaining issue which could cause some timeouts: some services hold FileLock which have the same identifier accross multiple tests. Signed-off-by: Sylvain Leclerc --- .github/workflows/main.yml | 2 +- requirements-test.txt | 4 +- .../test_filesystem_endpoints.py | 26 +- .../filesystem_blueprint/test_model.py | 13 +- .../filesystem/config/test_utils.py | 4 +- tests/variantstudy/test_command_factory.py | 766 +++++++++--------- 6 files changed, 410 insertions(+), 405 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5a7b9ad212..91523a511d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -53,7 +53,7 @@ jobs: pip install -r requirements-dev.txt - name: Test with pytest run: | - pytest --cov antarest --cov-report xml + pytest --cov antarest --cov-report xml -n auto - name: Archive code coverage results if: matrix.os == 'ubuntu-20.04' uses: actions/upload-artifact@v4 diff --git a/requirements-test.txt b/requirements-test.txt index 8e408b2677..10a360d7f4 100644 --- a/requirements-test.txt +++ b/requirements-test.txt @@ -1,7 +1,9 @@ -r requirements.txt checksumdir~=1.2.0 -pytest~=6.2.5 +pytest~=8.3.0 +pytest-xdist~=3.6.0 pytest-cov~=4.0.0 +pytest-mock~=3.14.0 # In this version DataFrame conversion to Excel is done using 'xlsxwriter' library. # But Excel files reading is done using 'openpyxl' library, during testing only. diff --git a/tests/integration/filesystem_blueprint/test_filesystem_endpoints.py b/tests/integration/filesystem_blueprint/test_filesystem_endpoints.py index d1e344e73d..ac1e9a36ff 100644 --- a/tests/integration/filesystem_blueprint/test_filesystem_endpoints.py +++ b/tests/integration/filesystem_blueprint/test_filesystem_endpoints.py @@ -13,10 +13,10 @@ import datetime import operator import re -import shutil import typing as t from pathlib import Path +from pytest_mock import MockerFixture from starlette.testclient import TestClient from tests.integration.conftest import RESOURCES_DIR @@ -93,6 +93,7 @@ def test_lifecycle( client: TestClient, user_access_token: str, admin_access_token: str, + mocker: MockerFixture, ) -> None: """ Test the lifecycle of the filesystem endpoints. @@ -102,7 +103,7 @@ def test_lifecycle( caplog: pytest caplog fixture. client: test client (tests.integration.conftest.client_fixture). user_access_token: access token of a classic user (tests.integration.conftest.user_access_token_fixture). - admin_access_token: access token of an admin user (tests.integration.conftest.admin_access_token_fixture). + admin_access_token: access token of an admin user (tests.integration.conftestin_access_token_fixture). """ # NOTE: all the following paths are based on the configuration defined in the app_fixture. archive_dir = tmp_path / "archive_dir" @@ -165,26 +166,25 @@ def test_lifecycle( err_count += 1 # Known filesystem + mocker.patch("shutil.disk_usage", return_value=(100, 200, 300)) res = client.get("/v1/filesystem/ws", headers=user_headers) assert res.status_code == 200, res.json() actual = sorted(res.json(), key=operator.itemgetter("name")) - # Both mount point are in the same filesystem, which is the `tmp_path` filesystem - total_bytes, used_bytes, free_bytes = shutil.disk_usage(tmp_path) expected = [ { "name": "default", "path": str(default_workspace), - "total_bytes": total_bytes, - "used_bytes": used_bytes, - "free_bytes": free_bytes, + "total_bytes": 100, + "used_bytes": 200, + "free_bytes": 300, "message": AnyDiskUsagePercent(), }, { "name": "ext", "path": str(ext_workspace_path), - "total_bytes": total_bytes, - "used_bytes": used_bytes, - "free_bytes": free_bytes, + "total_bytes": 100, + "used_bytes": 200, + "free_bytes": 300, "message": AnyDiskUsagePercent(), }, ] @@ -206,9 +206,9 @@ def test_lifecycle( expected = { "name": "default", "path": str(default_workspace), - "total_bytes": total_bytes, - "used_bytes": used_bytes, - "free_bytes": free_bytes, + "total_bytes": 100, + "used_bytes": 200, + "free_bytes": 300, "message": AnyDiskUsagePercent(), } assert actual == expected diff --git a/tests/integration/filesystem_blueprint/test_model.py b/tests/integration/filesystem_blueprint/test_model.py index 2e4932dd9c..48742b499b 100644 --- a/tests/integration/filesystem_blueprint/test_model.py +++ b/tests/integration/filesystem_blueprint/test_model.py @@ -16,6 +16,8 @@ import shutil from pathlib import Path +from pytest_mock import MockerFixture + from antarest.core.filesystem_blueprint import FileInfoDTO, FilesystemDTO, MountPointDTO @@ -63,15 +65,16 @@ def test_from_path__missing_file(self) -> None: assert dto.free_bytes == 0 assert dto.message.startswith("N/A:"), dto.message - def test_from_path__file(self, tmp_path: Path) -> None: + def test_from_path__file(self, tmp_path: Path, mocker: MockerFixture) -> None: + mocker.patch("shutil.disk_usage", return_value=(100, 200, 300)) + name = "foo" dto = asyncio.run(MountPointDTO.from_path(name, tmp_path)) - total_bytes, used_bytes, free_bytes = shutil.disk_usage(tmp_path) assert dto.name == name assert dto.path == tmp_path - assert dto.total_bytes == total_bytes - assert dto.used_bytes == used_bytes - assert dto.free_bytes == free_bytes + assert dto.total_bytes == 100 + assert dto.used_bytes == 200 + assert dto.free_bytes == 300 assert re.fullmatch(r"\d+(?:\.\d+)?% used", dto.message), dto.message diff --git a/tests/storage/repository/filesystem/config/test_utils.py b/tests/storage/repository/filesystem/config/test_utils.py index 3fed1bc5ba..cf470df38f 100644 --- a/tests/storage/repository/filesystem/config/test_utils.py +++ b/tests/storage/repository/filesystem/config/test_utils.py @@ -33,12 +33,12 @@ def test_transform_name_to_id__valid_chars(name): assert transform_name_to_id(name, lower=False) == name -@pytest.mark.parametrize("name", set(string.punctuation) - set(VALID_CHARS)) +@pytest.mark.parametrize("name", sorted(set(string.punctuation) - set(VALID_CHARS))) def test_transform_name_to_id__punctuation(name): assert not transform_name_to_id(name) -@pytest.mark.parametrize("name", set(string.whitespace) - set(VALID_CHARS)) +@pytest.mark.parametrize("name", sorted(set(string.whitespace) - set(VALID_CHARS))) def test_transform_name_to_id__whitespace(name): assert not transform_name_to_id(name) diff --git a/tests/variantstudy/test_command_factory.py b/tests/variantstudy/test_command_factory.py index f20985f808..b78ba393e5 100644 --- a/tests/variantstudy/test_command_factory.py +++ b/tests/variantstudy/test_command_factory.py @@ -13,6 +13,7 @@ import importlib import itertools import pkgutil +from typing import List, Set from unittest.mock import Mock import pytest @@ -25,18 +26,385 @@ from antarest.study.storage.variantstudy.model.command.icommand import ICommand from antarest.study.storage.variantstudy.model.model import CommandDTO +COMMANDS: List[CommandDTO] = [ + CommandDTO( + action=CommandName.CREATE_AREA.value, + args={"area_name": "area_name"}, + ), + CommandDTO( + action=CommandName.CREATE_AREA.value, + args=[ + {"area_name": "area_name"}, + {"area_name": "area2"}, + ], + ), + CommandDTO( + action=CommandName.REMOVE_AREA.value, + args={"id": "id"}, + ), + CommandDTO( + action=CommandName.REMOVE_AREA.value, + args=[{"id": "id"}], + ), + CommandDTO( + action=CommandName.CREATE_DISTRICT.value, + args={ + "name": "id", + "filter_items": ["a"], + "output": True, + "comments": "", + }, + ), + CommandDTO( + action=CommandName.CREATE_DISTRICT.value, + args=[ + { + "name": "id", + "base_filter": "add-all", + "output": True, + "comments": "", + } + ], + ), + CommandDTO( + action=CommandName.REMOVE_DISTRICT.value, + args={"id": "id"}, + ), + CommandDTO( + action=CommandName.REMOVE_DISTRICT.value, + args=[{"id": "id"}], + ), + CommandDTO( + action=CommandName.CREATE_LINK.value, + args={ + "area1": "area1", + "area2": "area2", + "parameters": {}, + "series": "series", + }, + ), + CommandDTO( + action=CommandName.CREATE_LINK.value, + args=[ + { + "area1": "area1", + "area2": "area2", + "parameters": {}, + "series": "series", + } + ], + ), + CommandDTO( + action=CommandName.REMOVE_LINK.value, + args={ + "area1": "area1", + "area2": "area2", + }, + ), + CommandDTO( + action=CommandName.REMOVE_LINK.value, + args=[ + { + "area1": "area1", + "area2": "area2", + } + ], + ), + CommandDTO( + action=CommandName.CREATE_BINDING_CONSTRAINT.value, + args={"name": "name"}, + ), + CommandDTO( + action=CommandName.CREATE_BINDING_CONSTRAINT.value, + args=[ + { + "name": "name", + "enabled": True, + "time_step": "hourly", + "operator": "equal", + "values": "values", + "group": "group_1", + }, + ], + ), + CommandDTO( + action=CommandName.UPDATE_BINDING_CONSTRAINT.value, + args={ + "id": "id", + "enabled": True, + "time_step": "hourly", + "operator": "equal", + "values": "values", + }, + ), + CommandDTO( + action=CommandName.UPDATE_BINDING_CONSTRAINT.value, + args=[ + { + "id": "id", + "enabled": True, + "time_step": "hourly", + "operator": "equal", + } + ], + ), + CommandDTO( + action=CommandName.REMOVE_BINDING_CONSTRAINT.value, + args={"id": "id"}, + ), + CommandDTO( + action=CommandName.REMOVE_BINDING_CONSTRAINT.value, + args=[{"id": "id"}], + ), + CommandDTO( + action=CommandName.CREATE_THERMAL_CLUSTER.value, + args={ + "area_id": "area_name", + "cluster_name": "cluster_name", + "parameters": { + "group": "group", + "unitcount": "unitcount", + "nominalcapacity": "nominalcapacity", + "marginal-cost": "marginal-cost", + "market-bid-cost": "market-bid-cost", + }, + "prepro": "prepro", + "modulation": "modulation", + }, + ), + CommandDTO( + action=CommandName.CREATE_THERMAL_CLUSTER.value, + args=[ + { + "area_id": "area_name", + "cluster_name": "cluster_name", + "parameters": { + "group": "group", + "unitcount": "unitcount", + "nominalcapacity": "nominalcapacity", + "marginal-cost": "marginal-cost", + "market-bid-cost": "market-bid-cost", + }, + "prepro": "prepro", + "modulation": "modulation", + } + ], + ), + CommandDTO( + action=CommandName.REMOVE_THERMAL_CLUSTER.value, + args={"area_id": "area_name", "cluster_id": "cluster_name"}, + ), + CommandDTO( + action=CommandName.REMOVE_THERMAL_CLUSTER.value, + args=[{"area_id": "area_name", "cluster_id": "cluster_name"}], + ), + CommandDTO( + action=CommandName.CREATE_RENEWABLES_CLUSTER.value, + args={ + "area_id": "area_name", + "cluster_name": "cluster_name", + "parameters": { + "name": "name", + "ts-interpretation": "power-generation", + }, + }, + ), + CommandDTO( + action=CommandName.CREATE_RENEWABLES_CLUSTER.value, + args=[ + { + "area_id": "area_name", + "cluster_name": "cluster_name", + "parameters": { + "name": "name", + "ts-interpretation": "power-generation", + }, + } + ], + ), + CommandDTO( + action=CommandName.REMOVE_RENEWABLES_CLUSTER.value, + args={"area_id": "area_name", "cluster_id": "cluster_name"}, + ), + CommandDTO( + action=CommandName.REMOVE_RENEWABLES_CLUSTER.value, + args=[{"area_id": "area_name", "cluster_id": "cluster_name"}], + ), + CommandDTO( + action=CommandName.REPLACE_MATRIX.value, + args={"target": "target_element", "matrix": "matrix"}, + ), + CommandDTO( + action=CommandName.REPLACE_MATRIX.value, + args=[{"target": "target_element", "matrix": "matrix"}], + ), + CommandDTO( + action=CommandName.UPDATE_CONFIG.value, + args={"target": "target", "data": {}}, + ), + CommandDTO( + action=CommandName.UPDATE_CONFIG.value, + args=[{"target": "target", "data": {}}], + ), + CommandDTO( + action=CommandName.UPDATE_COMMENTS.value, + args={"comments": "comments"}, + ), + CommandDTO( + action=CommandName.UPDATE_COMMENTS.value, + args=[{"comments": "comments"}], + ), + CommandDTO( + action=CommandName.UPDATE_FILE.value, + args={ + "target": "settings/resources/study", + "b64Data": "", + }, + ), + CommandDTO( + action=CommandName.UPDATE_DISTRICT.value, + args={"id": "id", "filter_items": ["a"]}, + ), + CommandDTO( + action=CommandName.UPDATE_DISTRICT.value, + args=[{"id": "id", "base_filter": "add-all"}], + ), + CommandDTO( + action=CommandName.UPDATE_PLAYLIST.value, + args=[{"active": True, "items": [1, 3], "reverse": False}], + ), + CommandDTO( + action=CommandName.UPDATE_PLAYLIST.value, + args={ + "active": True, + "items": [1, 3], + "weights": {1: 5.0}, + "reverse": False, + }, + ), + CommandDTO( + action=CommandName.UPDATE_SCENARIO_BUILDER.value, + args={ + "data": { + "ruleset test": { + "l": {"area1": {"0": 1}}, + "ntc": {"area1 / area2": {"1": 23}}, + "t": {"area1": {"thermal": {"1": 2}}}, + }, + } + }, + ), + CommandDTO( + action=CommandName.CREATE_ST_STORAGE.value, + args={ + "area_id": "area 1", + "parameters": { + "name": "Storage 1", + "group": "Battery", + "injectionnominalcapacity": 0, + "withdrawalnominalcapacity": 0, + "reservoircapacity": 0, + "efficiency": 1, + "initiallevel": 0, + "initialleveloptim": False, + }, + "pmax_injection": "matrix://59ea6c83-6348-466d-9530-c35c51ca4c37", + "pmax_withdrawal": "matrix://5f988548-dadc-4bbb-8ce8-87a544dbf756", + "lower_rule_curve": "matrix://8ce4fcea-cc97-4d2c-b641-a27a53454612", + "upper_rule_curve": "matrix://8ce614c8-c687-41af-8b24-df8a49cc52af", + "inflows": "matrix://df9b25e1-e3f7-4a57-8182-0ff9791439e5", + }, + ), + CommandDTO( + action=CommandName.CREATE_ST_STORAGE.value, + args=[ + { + "area_id": "area 1", + "parameters": { + "efficiency": 1, + "group": "Battery", + "initiallevel": 0, + "initialleveloptim": False, + "injectionnominalcapacity": 0, + "name": "Storage 1", + "reservoircapacity": 0, + "withdrawalnominalcapacity": 0, + }, + "pmax_injection": "matrix://59ea6c83-6348-466d-9530-c35c51ca4c37", + "pmax_withdrawal": "matrix://5f988548-dadc-4bbb-8ce8-87a544dbf756", + "lower_rule_curve": "matrix://8ce4fcea-cc97-4d2c-b641-a27a53454612", + "upper_rule_curve": "matrix://8ce614c8-c687-41af-8b24-df8a49cc52af", + "inflows": "matrix://df9b25e1-e3f7-4a57-8182-0ff9791439e5", + }, + { + "area_id": "area 1", + "parameters": { + "efficiency": 0.94, + "group": "Battery", + "initiallevel": 0, + "initialleveloptim": False, + "injectionnominalcapacity": 0, + "name": "Storage 2", + "reservoircapacity": 0, + "withdrawalnominalcapacity": 0, + }, + "pmax_injection": "matrix://3f5b3746-3995-49b7-a6da-622633472e05", + "pmax_withdrawal": "matrix://4b64a31f-927b-4887-b4cd-adcddd39bdcd", + "lower_rule_curve": "matrix://16c7c3ae-9824-4ef2-aa68-51145884b025", + "upper_rule_curve": "matrix://9a6104e9-990a-415f-a6e2-57507e13b58c", + "inflows": "matrix://e8923768-9bdd-40c2-a6ea-2da2523be727", + }, + ], + ), + CommandDTO( + action=CommandName.REMOVE_ST_STORAGE.value, + args={ + "area_id": "area 1", + "storage_id": "storage 1", + }, + ), + CommandDTO( + action=CommandName.REMOVE_ST_STORAGE.value, + args=[ + { + "area_id": "area 1", + "storage_id": "storage 1", + }, + { + "area_id": "area 1", + "storage_id": "storage 2", + }, + ], + ), + CommandDTO( + action=CommandName.GENERATE_THERMAL_CLUSTER_TIMESERIES.value, + args=[{}], + ), +] + + +@pytest.fixture +def command_factory() -> CommandFactory: + def get_matrix_id(matrix: str) -> str: + # str.removeprefix() is not available in Python 3.8 + prefix = "matrix://" + if matrix.startswith(prefix): + return matrix[len(prefix) :] + return matrix + + return CommandFactory( + generator_matrix_constants=Mock(spec=GeneratorMatrixConstants), + matrix_service=Mock(spec=MatrixService, get_matrix_id=get_matrix_id), + patch_service=Mock(spec=PatchService), + ) + class TestCommandFactory: - # noinspection SpellCheckingInspection - def setup_class(self): + def _get_command_classes(self) -> Set[str]: """ - Set up the test class. - Imports all modules from the `antarest.study.storage.variantstudy.model.command` package and creates a set of command class names derived from the `ICommand` abstract class. The objective is to ensure that the unit test covers all commands in this package. - - This method is executed once before any tests in the test class are run. """ for module_loader, name, ispkg in pkgutil.iter_modules(["antarest/study/storage/variantstudy/model/command"]): importlib.import_module( @@ -44,383 +412,21 @@ def setup_class(self): package="antarest.study.storage.variantstudy.model.command", ) abstract_commands = {"AbstractBindingConstraintCommand"} - self.command_class_set = { - cmd.__name__ for cmd in ICommand.__subclasses__() if cmd.__name__ not in abstract_commands - } + return {cmd.__name__ for cmd in ICommand.__subclasses__() if cmd.__name__ not in abstract_commands} + + def test_all_commands_are_tested(self, command_factory: CommandFactory): + commands = sum([command_factory.to_command(command_dto=cmd) for cmd in COMMANDS], []) + tested_classes = {c.__class__.__name__ for c in commands} + + assert self._get_command_classes().issubset(tested_classes) # noinspection SpellCheckingInspection @pytest.mark.parametrize( "command_dto", - [ - CommandDTO( - action=CommandName.CREATE_AREA.value, - args={"area_name": "area_name"}, - ), - CommandDTO( - action=CommandName.CREATE_AREA.value, - args=[ - {"area_name": "area_name"}, - {"area_name": "area2"}, - ], - ), - CommandDTO( - action=CommandName.REMOVE_AREA.value, - args={"id": "id"}, - ), - CommandDTO( - action=CommandName.REMOVE_AREA.value, - args=[{"id": "id"}], - ), - CommandDTO( - action=CommandName.CREATE_DISTRICT.value, - args={ - "name": "id", - "filter_items": ["a"], - "output": True, - "comments": "", - }, - ), - CommandDTO( - action=CommandName.CREATE_DISTRICT.value, - args=[ - { - "name": "id", - "base_filter": "add-all", - "output": True, - "comments": "", - } - ], - ), - CommandDTO( - action=CommandName.REMOVE_DISTRICT.value, - args={"id": "id"}, - ), - CommandDTO( - action=CommandName.REMOVE_DISTRICT.value, - args=[{"id": "id"}], - ), - CommandDTO( - action=CommandName.CREATE_LINK.value, - args={ - "area1": "area1", - "area2": "area2", - "parameters": {}, - "series": "series", - }, - ), - CommandDTO( - action=CommandName.CREATE_LINK.value, - args=[ - { - "area1": "area1", - "area2": "area2", - "parameters": {}, - "series": "series", - } - ], - ), - CommandDTO( - action=CommandName.REMOVE_LINK.value, - args={ - "area1": "area1", - "area2": "area2", - }, - ), - CommandDTO( - action=CommandName.REMOVE_LINK.value, - args=[ - { - "area1": "area1", - "area2": "area2", - } - ], - ), - CommandDTO( - action=CommandName.CREATE_BINDING_CONSTRAINT.value, - args={"name": "name"}, - ), - CommandDTO( - action=CommandName.CREATE_BINDING_CONSTRAINT.value, - args=[ - { - "name": "name", - "enabled": True, - "time_step": "hourly", - "operator": "equal", - "values": "values", - "group": "group_1", - }, - ], - ), - CommandDTO( - action=CommandName.UPDATE_BINDING_CONSTRAINT.value, - args={ - "id": "id", - "enabled": True, - "time_step": "hourly", - "operator": "equal", - "values": "values", - }, - ), - CommandDTO( - action=CommandName.UPDATE_BINDING_CONSTRAINT.value, - args=[ - { - "id": "id", - "enabled": True, - "time_step": "hourly", - "operator": "equal", - } - ], - ), - CommandDTO( - action=CommandName.REMOVE_BINDING_CONSTRAINT.value, - args={"id": "id"}, - ), - CommandDTO( - action=CommandName.REMOVE_BINDING_CONSTRAINT.value, - args=[{"id": "id"}], - ), - CommandDTO( - action=CommandName.CREATE_THERMAL_CLUSTER.value, - args={ - "area_id": "area_name", - "cluster_name": "cluster_name", - "parameters": { - "group": "group", - "unitcount": "unitcount", - "nominalcapacity": "nominalcapacity", - "marginal-cost": "marginal-cost", - "market-bid-cost": "market-bid-cost", - }, - "prepro": "prepro", - "modulation": "modulation", - }, - ), - CommandDTO( - action=CommandName.CREATE_THERMAL_CLUSTER.value, - args=[ - { - "area_id": "area_name", - "cluster_name": "cluster_name", - "parameters": { - "group": "group", - "unitcount": "unitcount", - "nominalcapacity": "nominalcapacity", - "marginal-cost": "marginal-cost", - "market-bid-cost": "market-bid-cost", - }, - "prepro": "prepro", - "modulation": "modulation", - } - ], - ), - CommandDTO( - action=CommandName.REMOVE_THERMAL_CLUSTER.value, - args={"area_id": "area_name", "cluster_id": "cluster_name"}, - ), - CommandDTO( - action=CommandName.REMOVE_THERMAL_CLUSTER.value, - args=[{"area_id": "area_name", "cluster_id": "cluster_name"}], - ), - CommandDTO( - action=CommandName.CREATE_RENEWABLES_CLUSTER.value, - args={ - "area_id": "area_name", - "cluster_name": "cluster_name", - "parameters": { - "name": "name", - "ts-interpretation": "power-generation", - }, - }, - ), - CommandDTO( - action=CommandName.CREATE_RENEWABLES_CLUSTER.value, - args=[ - { - "area_id": "area_name", - "cluster_name": "cluster_name", - "parameters": { - "name": "name", - "ts-interpretation": "power-generation", - }, - } - ], - ), - CommandDTO( - action=CommandName.REMOVE_RENEWABLES_CLUSTER.value, - args={"area_id": "area_name", "cluster_id": "cluster_name"}, - ), - CommandDTO( - action=CommandName.REMOVE_RENEWABLES_CLUSTER.value, - args=[{"area_id": "area_name", "cluster_id": "cluster_name"}], - ), - CommandDTO( - action=CommandName.REPLACE_MATRIX.value, - args={"target": "target_element", "matrix": "matrix"}, - ), - CommandDTO( - action=CommandName.REPLACE_MATRIX.value, - args=[{"target": "target_element", "matrix": "matrix"}], - ), - CommandDTO( - action=CommandName.UPDATE_CONFIG.value, - args={"target": "target", "data": {}}, - ), - CommandDTO( - action=CommandName.UPDATE_CONFIG.value, - args=[{"target": "target", "data": {}}], - ), - CommandDTO( - action=CommandName.UPDATE_COMMENTS.value, - args={"comments": "comments"}, - ), - CommandDTO( - action=CommandName.UPDATE_COMMENTS.value, - args=[{"comments": "comments"}], - ), - CommandDTO( - action=CommandName.UPDATE_FILE.value, - args={ - "target": "settings/resources/study", - "b64Data": "", - }, - ), - CommandDTO( - action=CommandName.UPDATE_DISTRICT.value, - args={"id": "id", "filter_items": ["a"]}, - ), - CommandDTO( - action=CommandName.UPDATE_DISTRICT.value, - args=[{"id": "id", "base_filter": "add-all"}], - ), - CommandDTO( - action=CommandName.UPDATE_PLAYLIST.value, - args=[{"active": True, "items": [1, 3], "reverse": False}], - ), - CommandDTO( - action=CommandName.UPDATE_PLAYLIST.value, - args={ - "active": True, - "items": [1, 3], - "weights": {1: 5.0}, - "reverse": False, - }, - ), - CommandDTO( - action=CommandName.UPDATE_SCENARIO_BUILDER.value, - args={ - "data": { - "ruleset test": { - "l": {"area1": {"0": 1}}, - "ntc": {"area1 / area2": {"1": 23}}, - "t": {"area1": {"thermal": {"1": 2}}}, - }, - } - }, - ), - CommandDTO( - action=CommandName.CREATE_ST_STORAGE.value, - args={ - "area_id": "area 1", - "parameters": { - "name": "Storage 1", - "group": "Battery", - "injectionnominalcapacity": 0, - "withdrawalnominalcapacity": 0, - "reservoircapacity": 0, - "efficiency": 1, - "initiallevel": 0, - "initialleveloptim": False, - }, - "pmax_injection": "matrix://59ea6c83-6348-466d-9530-c35c51ca4c37", - "pmax_withdrawal": "matrix://5f988548-dadc-4bbb-8ce8-87a544dbf756", - "lower_rule_curve": "matrix://8ce4fcea-cc97-4d2c-b641-a27a53454612", - "upper_rule_curve": "matrix://8ce614c8-c687-41af-8b24-df8a49cc52af", - "inflows": "matrix://df9b25e1-e3f7-4a57-8182-0ff9791439e5", - }, - ), - CommandDTO( - action=CommandName.CREATE_ST_STORAGE.value, - args=[ - { - "area_id": "area 1", - "parameters": { - "efficiency": 1, - "group": "Battery", - "initiallevel": 0, - "initialleveloptim": False, - "injectionnominalcapacity": 0, - "name": "Storage 1", - "reservoircapacity": 0, - "withdrawalnominalcapacity": 0, - }, - "pmax_injection": "matrix://59ea6c83-6348-466d-9530-c35c51ca4c37", - "pmax_withdrawal": "matrix://5f988548-dadc-4bbb-8ce8-87a544dbf756", - "lower_rule_curve": "matrix://8ce4fcea-cc97-4d2c-b641-a27a53454612", - "upper_rule_curve": "matrix://8ce614c8-c687-41af-8b24-df8a49cc52af", - "inflows": "matrix://df9b25e1-e3f7-4a57-8182-0ff9791439e5", - }, - { - "area_id": "area 1", - "parameters": { - "efficiency": 0.94, - "group": "Battery", - "initiallevel": 0, - "initialleveloptim": False, - "injectionnominalcapacity": 0, - "name": "Storage 2", - "reservoircapacity": 0, - "withdrawalnominalcapacity": 0, - }, - "pmax_injection": "matrix://3f5b3746-3995-49b7-a6da-622633472e05", - "pmax_withdrawal": "matrix://4b64a31f-927b-4887-b4cd-adcddd39bdcd", - "lower_rule_curve": "matrix://16c7c3ae-9824-4ef2-aa68-51145884b025", - "upper_rule_curve": "matrix://9a6104e9-990a-415f-a6e2-57507e13b58c", - "inflows": "matrix://e8923768-9bdd-40c2-a6ea-2da2523be727", - }, - ], - ), - CommandDTO( - action=CommandName.REMOVE_ST_STORAGE.value, - args={ - "area_id": "area 1", - "storage_id": "storage 1", - }, - ), - CommandDTO( - action=CommandName.REMOVE_ST_STORAGE.value, - args=[ - { - "area_id": "area 1", - "storage_id": "storage 1", - }, - { - "area_id": "area 1", - "storage_id": "storage 2", - }, - ], - ), - CommandDTO( - action=CommandName.GENERATE_THERMAL_CLUSTER_TIMESERIES.value, - args=[{}], - ), - ], + COMMANDS, ) @pytest.mark.unit_test - def test_command_factory(self, command_dto: CommandDTO): - def get_matrix_id(matrix: str) -> str: - # str.removeprefix() is not available in Python 3.8 - prefix = "matrix://" - if matrix.startswith(prefix): - return matrix[len(prefix) :] - return matrix - - command_factory = CommandFactory( - generator_matrix_constants=Mock(spec=GeneratorMatrixConstants), - matrix_service=Mock(spec=MatrixService, get_matrix_id=get_matrix_id), - patch_service=Mock(spec=PatchService), - ) + def test_command_factory(self, command_dto: CommandDTO, command_factory: CommandFactory): commands = command_factory.to_command(command_dto=command_dto) if isinstance(command_dto.args, dict): @@ -440,12 +446,6 @@ def get_matrix_id(matrix: str) -> str: assert actual_args == expected_args assert actual_version == expected_version - self.command_class_set.discard(type(commands[0]).__name__) - - def teardown_class(self): - # Check that all command classes have been tested - assert not self.command_class_set - @pytest.mark.unit_test def test_unknown_command():