Skip to content

Commit 58ba3e6

Browse files
authored
Use solipsism, time-machine in *Pool tests (#1013)
This makes the tests less flaky. Closes #901
2 parents a3228e3 + ace425a commit 58ba3e6

File tree

3 files changed

+30
-32
lines changed

3 files changed

+30
-32
lines changed

tests/timeseries/_battery_pool/test_battery_pool_control_methods.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from datetime import datetime, timedelta, timezone
1010
from unittest.mock import AsyncMock, MagicMock
1111

12+
import async_solipsism
1213
import pytest
1314
from frequenz.channels import LatestValueCache, Sender
1415
from pytest_mock import MockerFixture
@@ -27,6 +28,12 @@
2728
from ..mock_microgrid import MockMicrogrid
2829

2930

31+
@pytest.fixture
32+
def event_loop_policy() -> async_solipsism.EventLoopPolicy:
33+
"""Event loop policy."""
34+
return async_solipsism.EventLoopPolicy()
35+
36+
3037
@dataclasses.dataclass(frozen=True)
3138
class Mocks:
3239
"""Mocks for the tests."""
@@ -89,11 +96,6 @@ async def _patch_battery_pool_status(
8996
If `battery_ids` is not None, the mock will always return `battery_ids`.
9097
Otherwise, it will return the requested batteries.
9198
"""
92-
mocker.patch.object(
93-
timeseries.battery_pool._methods, # pylint: disable=protected-access
94-
"WAIT_FOR_COMPONENT_DATA_SEC",
95-
0.1,
96-
)
9799
if battery_ids:
98100
mock = MagicMock(spec=ComponentPoolStatusTracker)
99101
mock.get_working_components.return_value = battery_ids

tests/timeseries/_ev_charger_pool/test_ev_charger_pool_control_methods.py

Lines changed: 16 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,16 @@
88
from datetime import datetime, timedelta, timezone
99
from unittest.mock import AsyncMock, MagicMock
1010

11+
import async_solipsism
1112
import pytest
13+
import time_machine
1214
from frequenz.channels import Receiver
1315
from frequenz.client.microgrid import EVChargerCableState, EVChargerComponentState
1416
from pytest_mock import MockerFixture
1517

1618
from frequenz.sdk import microgrid
1719
from frequenz.sdk.actor import ResamplerConfig, power_distributing
18-
from frequenz.sdk.actor.power_distributing import (
19-
ComponentPoolStatus,
20-
PowerDistributingActor,
21-
)
22-
from frequenz.sdk.actor.power_distributing._component_managers import EVChargerManager
23-
from frequenz.sdk.actor.power_distributing._component_managers._ev_charger_manager._config import (
24-
EVDistributionConfig,
25-
)
20+
from frequenz.sdk.actor.power_distributing import ComponentPoolStatus
2621
from frequenz.sdk.actor.power_distributing._component_pool_status_tracker import (
2722
ComponentPoolStatusTracker,
2823
)
@@ -38,6 +33,12 @@
3833
# pylint: disable=protected-access
3934

4035

36+
@pytest.fixture
37+
def event_loop_policy() -> async_solipsism.EventLoopPolicy:
38+
"""Event loop policy."""
39+
return async_solipsism.EventLoopPolicy()
40+
41+
4142
@pytest.fixture
4243
async def mocks(mocker: MockerFixture) -> typing.AsyncIterator[_Mocks]:
4344
"""Create the mocks."""
@@ -100,24 +101,6 @@ async def _patch_power_distributing_actor(
100101
self,
101102
mocker: MockerFixture,
102103
) -> None:
103-
dp = typing.cast(_DataPipeline, microgrid._data_pipeline._DATA_PIPELINE)
104-
pda = typing.cast(
105-
PowerDistributingActor, dp._ev_power_wrapper._power_distributing_actor
106-
)
107-
cm = typing.cast(
108-
EVChargerManager,
109-
pda._component_manager,
110-
)
111-
mocker.patch(
112-
"frequenz.sdk.microgrid._data_pipeline._DATA_PIPELINE._ev_power_wrapper"
113-
"._power_distributing_actor._component_manager._config",
114-
EVDistributionConfig(
115-
component_ids=cm._config.component_ids,
116-
initial_current=cm._config.initial_current,
117-
min_current=cm._config.min_current,
118-
increase_power_interval=timedelta(seconds=0.12),
119-
),
120-
)
121104
mocker.patch(
122105
"frequenz.sdk.microgrid._data_pipeline._DATA_PIPELINE._ev_power_wrapper"
123106
"._power_distributing_actor._component_manager._voltage_cache.get",
@@ -202,10 +185,12 @@ async def test_setting_power(
202185
mocker: MockerFixture,
203186
) -> None:
204187
"""Test setting power."""
188+
traveller = time_machine.travel(datetime(2012, 12, 12))
189+
mock_time = traveller.start()
190+
205191
set_power = typing.cast(
206192
AsyncMock, microgrid.connection_manager.get().api_client.set_power
207193
)
208-
209194
await self._init_ev_chargers(mocks)
210195
ev_charger_pool = microgrid.new_ev_charger_pool(priority=5)
211196
await self._patch_ev_pool_status(mocks, mocker)
@@ -228,6 +213,7 @@ async def test_setting_power(
228213
self._assert_report(
229214
await bounds_rx.receive(), power=40000.0, lower=0.0, upper=44160.0
230215
)
216+
mock_time.shift(timedelta(seconds=60))
231217
await asyncio.sleep(0.15)
232218

233219
# Components are set initial power
@@ -237,6 +223,7 @@ async def test_setting_power(
237223
# All available power is allocated. 3 chargers are set to 11040.0
238224
# and the last one is set to 6880.0
239225
set_power.reset_mock()
226+
mock_time.shift(timedelta(seconds=60))
240227
await asyncio.sleep(0.15)
241228
assert set_power.call_count == 4
242229

@@ -255,3 +242,5 @@ async def test_setting_power(
255242
stopped_evs = [x.args for x in set_power.call_args_list if x.args[1] == 0.0]
256243
assert 1 == len(stopped_evs)
257244
assert stopped_evs[0][0] in [evc[0] for evc in evs_11040]
245+
246+
traveller.stop()

tests/timeseries/_pv_pool/test_pv_pool_control_methods.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from datetime import datetime, timedelta, timezone
99
from unittest.mock import AsyncMock
1010

11+
import async_solipsism
1112
import pytest
1213
from frequenz.channels import Receiver
1314
from frequenz.client.microgrid import InverterComponentState
@@ -25,6 +26,12 @@
2526
from ..mock_microgrid import MockMicrogrid
2627

2728

29+
@pytest.fixture
30+
def event_loop_policy() -> async_solipsism.EventLoopPolicy:
31+
"""Event loop policy."""
32+
return async_solipsism.EventLoopPolicy()
33+
34+
2835
@pytest.fixture
2936
async def mocks(mocker: MockerFixture) -> typing.AsyncIterator[_Mocks]:
3037
"""Create the mocks."""

0 commit comments

Comments
 (0)