Skip to content

Commit 3a51bf9

Browse files
committed
feat(tests): Tests electrical component connections
Adds tests for list_microgrid_electrical_component_connections, covering success, empty results, and error cases to improve reliability. Signed-off-by: eduardiazf <[email protected]>
1 parent 4f11a39 commit 3a51bf9

File tree

7 files changed

+147
-2
lines changed

7 files changed

+147
-2
lines changed

src/frequenz/client/assets/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from ._client import AssetsApiClient
77
from ._delivery_area import DeliveryArea, EnergyMarketCodeType
8+
from ._lifetime import Lifetime
89
from ._location import Location
910
from ._microgrid import Microgrid, MicrogridStatus
1011

@@ -15,4 +16,5 @@
1516
"Microgrid",
1617
"MicrogridStatus",
1718
"Location",
19+
"Lifetime",
1820
]

src/frequenz/client/assets/_lifetime.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@ class Lifetime:
1313
"""An active operational period of a microgrid asset.
1414
1515
Warning:
16-
The [`end`][frequenz.client.microgrid.Lifetime.end] timestamp indicates that the
16+
The [`end`][frequenz.client.assets.Lifetime.end] timestamp indicates that the
1717
asset has been permanently removed from the system.
1818
"""
1919

2020
start: datetime | None = None
2121
"""The moment when the asset became operationally active.
2222
2323
If `None`, the asset is considered to be active in any past moment previous to the
24-
[`end`][frequenz.client.microgrid.Lifetime.end].
24+
[`end`][frequenz.client.assets.Lifetime.end].
2525
"""
2626

2727
end: datetime | None = None

src/frequenz/client/assets/electrical_component/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from ._capacitor_bank import CapacitorBank
1515
from ._category import ElectricalComponentCategory
1616
from ._chp import Chp
17+
from ._connection import ComponentConnection
1718
from ._converter import Converter
1819
from ._crypto_miner import CryptoMiner
1920
from ._electrical_component import ElectricalComponent
@@ -87,4 +88,5 @@
8788
"StaticTransferSwitch",
8889
"UninterruptiblePowerSupply",
8990
"WindTurbine",
91+
"ComponentConnection",
9092
]
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# License: MIT
2+
# Copyright © 2025 Frequenz Energy-as-a-Service GmbH
3+
4+
"""Test list_connections with no connections: result should be empty."""
5+
6+
from typing import Any
7+
8+
from frequenz.api.assets.v1 import assets_pb2
9+
10+
# No client_args or client_kwargs needed for this call
11+
12+
13+
def assert_stub_method_call(stub_method: Any) -> None:
14+
"""Assert that the gRPC request matches the expected request."""
15+
stub_method.assert_called_once_with(
16+
assets_pb2.ListMicrogridElectricalComponentConnectionsRequest(
17+
microgrid_id=1234, source_component_ids=[], destination_component_ids=[]
18+
),
19+
timeout=60.0,
20+
)
21+
22+
23+
client_args = (1234,)
24+
grpc_response = assets_pb2.ListMicrogridElectricalComponentConnectionsResponse(
25+
connections=[]
26+
)
27+
28+
29+
def assert_client_result(result: Any) -> None: # noqa: D103
30+
"""Assert that the client result is an empty list."""
31+
assert not list(result)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# License: MIT
2+
# Copyright © 2025 Frequenz Energy-as-a-Service GmbH
3+
4+
"""Test list_electrical_components with error."""
5+
6+
from typing import Any
7+
8+
from frequenz.api.assets.v1 import assets_pb2
9+
from grpc import StatusCode
10+
11+
from frequenz.client.assets.exceptions import PermissionDenied
12+
from tests.util import make_grpc_error
13+
14+
15+
def assert_stub_method_call(stub_method: Any) -> None:
16+
"""Assert that the gRPC request matches the expected request."""
17+
stub_method.assert_called_once_with(
18+
assets_pb2.ListMicrogridElectricalComponentConnectionsRequest(
19+
microgrid_id=1234
20+
),
21+
timeout=60.0,
22+
)
23+
24+
25+
client_args = (1234,)
26+
grpc_response = make_grpc_error(StatusCode.PERMISSION_DENIED)
27+
28+
29+
def assert_client_exception(exception: Exception) -> None:
30+
"""Assert that the client exception matches the expected error."""
31+
assert isinstance(exception, PermissionDenied)
32+
assert exception.grpc_error == grpc_response
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# License: MIT
2+
# Copyright © 2025 Frequenz Energy-as-a-Service GmbH
3+
4+
"""Test data for successful connection listing."""
5+
6+
from datetime import datetime, timezone
7+
from typing import Any
8+
9+
from frequenz.api.assets.v1 import assets_pb2
10+
from frequenz.api.common.v1alpha8.microgrid import lifetime_pb2
11+
from frequenz.api.common.v1alpha8.microgrid.electrical_components import (
12+
electrical_components_pb2,
13+
)
14+
from frequenz.client.base.conversion import to_timestamp
15+
from frequenz.client.common.microgrid.components import ComponentId
16+
17+
from frequenz.client.assets import Lifetime
18+
from frequenz.client.assets.electrical_component import ComponentConnection
19+
20+
21+
def assert_stub_method_call(stub_method: Any) -> None:
22+
"""Assert that the gRPC request matches the expected request."""
23+
stub_method.assert_called_once_with(
24+
assets_pb2.ListMicrogridElectricalComponentConnectionsRequest(
25+
microgrid_id=1234, source_component_ids=[], destination_component_ids=[]
26+
),
27+
timeout=60.0,
28+
)
29+
30+
31+
client_args = (1234,)
32+
lifetime_start = datetime(2023, 1, 1, 0, 0, 0, tzinfo=timezone.utc)
33+
grpc_response = assets_pb2.ListMicrogridElectricalComponentConnectionsResponse(
34+
connections=[
35+
electrical_components_pb2.ElectricalComponentConnection(
36+
source_electrical_component_id=1, destination_electrical_component_id=2
37+
),
38+
electrical_components_pb2.ElectricalComponentConnection(
39+
source_electrical_component_id=2,
40+
destination_electrical_component_id=3,
41+
operational_lifetime=lifetime_pb2.Lifetime(
42+
start_timestamp=to_timestamp(lifetime_start)
43+
),
44+
),
45+
]
46+
)
47+
48+
49+
def assert_client_result(actual_result: Any) -> None:
50+
"""Assert that the client result matches the expected connections list."""
51+
assert list(actual_result) == [
52+
ComponentConnection(
53+
source=ComponentId(1),
54+
destination=ComponentId(2),
55+
),
56+
ComponentConnection(
57+
source=ComponentId(2),
58+
destination=ComponentId(3),
59+
operational_lifetime=Lifetime(start=lifetime_start),
60+
),
61+
]

tests/test_client.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,20 @@ async def test_list_microgrid_electrical_components(
5050
) -> None:
5151
"""Test list_microgrid_electrical_components method."""
5252
await spec.test_unary_unary_call(client, "ListMicrogridElectricalComponents")
53+
54+
55+
@pytest.mark.asyncio
56+
@pytest.mark.parametrize(
57+
"spec",
58+
get_test_specs(
59+
"list_microgrid_electrical_component_connections", tests_dir=TESTS_DIR
60+
),
61+
ids=str,
62+
)
63+
async def test_list_connections(
64+
client: AssetsApiClient, spec: ApiClientTestCaseSpec
65+
) -> None:
66+
"""Test list_connections method."""
67+
await spec.test_unary_unary_call(
68+
client, "ListMicrogridElectricalComponentConnections"
69+
)

0 commit comments

Comments
 (0)