From 8bd41253902086df3270f3525eb44dfcfc73995e Mon Sep 17 00:00:00 2001 From: Joakim Plate Date: Wed, 23 Nov 2022 20:53:28 +0100 Subject: [PATCH] Test corrections noticed during pytest upgrade (#82579) * Withing trigger a call to coordinator after init * Stop discovery task on STOP event * Stop dsmr connection task on STOP * Use autospec in modem_serial tests close on AioSerial is non async, and should not be mocked as a coroutine * Make sure responder is specced correctly tests/components/emulated_hue/test_init.py::test_setup_works /Users/joakim/src/hass/home-assistant/homeassistant/components/emulated_hue/__init__.py:119: RuntimeWarning: coroutine 'AsyncMockMixin._execute_mock_call' was never awaited protocol.close() * Don't assume Pymodbus is the only thing logging * Use gather instead of wait ``` homeassistant/components/homeassistant/__init__.py:208: DeprecationWarning: The explicit passing of coroutine objects to asyncio.wait() is deprecated since Python 3.8, and scheduled for removal in Python 3.11. ``` * Increase wait time for automation tests Assuming exit within 1 seconds is unreasonable on a potentially loaded test machine. * Avoid changing app state after startup --- homeassistant/components/dsmr/sensor.py | 11 ++++++++++- homeassistant/components/homeassistant/__init__.py | 2 +- homeassistant/components/http/ban.py | 5 ++--- homeassistant/components/lifx/__init__.py | 13 +++++++++++-- tests/components/automation/test_init.py | 4 ++-- tests/components/emulated_hue/test_init.py | 4 ++++ tests/components/modbus/test_init.py | 2 +- tests/components/modem_callerid/test_init.py | 4 ++-- tests/components/withings/test_init.py | 4 ++++ 9 files changed, 37 insertions(+), 12 deletions(-) diff --git a/homeassistant/components/dsmr/sensor.py b/homeassistant/components/dsmr/sensor.py index 02a14601cc3..5cbd3e14be0 100644 --- a/homeassistant/components/dsmr/sensor.py +++ b/homeassistant/components/dsmr/sensor.py @@ -30,7 +30,7 @@ from homeassistant.const import ( EVENT_HOMEASSISTANT_STOP, VOLUME_CUBIC_METERS, ) -from homeassistant.core import CoreState, HomeAssistant, callback +from homeassistant.core import CoreState, Event, HomeAssistant, callback from homeassistant.helpers.entity import DeviceInfo, EntityCategory from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import EventType, StateType @@ -505,6 +505,15 @@ async def async_setup_entry( # Can't be hass.async_add_job because job runs forever task = asyncio.create_task(connect_and_reconnect()) + @callback + async def _async_stop(_: Event) -> None: + task.cancel() + + # Make sure task is cancelled on shutdown (or tests complete) + entry.async_on_unload( + hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, _async_stop) + ) + # Save the task to be able to cancel it when unloading hass.data[DOMAIN][entry.entry_id][DATA_TASK] = task diff --git a/homeassistant/components/homeassistant/__init__.py b/homeassistant/components/homeassistant/__init__.py index 81d79b03c10..7e557e0808e 100644 --- a/homeassistant/components/homeassistant/__init__.py +++ b/homeassistant/components/homeassistant/__init__.py @@ -205,7 +205,7 @@ async def async_setup(hass: ha.HomeAssistant, config: ConfigType) -> bool: # no ] if tasks: - await asyncio.wait(tasks) + await asyncio.gather(*tasks) async_register_admin_service( hass, ha.DOMAIN, SERVICE_HOMEASSISTANT_STOP, async_handle_core_service diff --git a/homeassistant/components/http/ban.py b/homeassistant/components/http/ban.py index d2f5f9d8ba5..7be8634212a 100644 --- a/homeassistant/components/http/ban.py +++ b/homeassistant/components/http/ban.py @@ -51,12 +51,11 @@ def setup_bans(hass: HomeAssistant, app: Application, login_threshold: int) -> N app.middlewares.append(ban_middleware) app[KEY_FAILED_LOGIN_ATTEMPTS] = defaultdict(int) app[KEY_LOGIN_THRESHOLD] = login_threshold + app[KEY_BAN_MANAGER] = IpBanManager(hass) async def ban_startup(app: Application) -> None: """Initialize bans when app starts up.""" - ban_manager = IpBanManager(hass) - await ban_manager.async_load() - app[KEY_BAN_MANAGER] = ban_manager + await app[KEY_BAN_MANAGER].async_load() app.on_startup.append(ban_startup) diff --git a/homeassistant/components/lifx/__init__.py b/homeassistant/components/lifx/__init__.py index 786ddd6abbf..abe35c0a0d8 100644 --- a/homeassistant/components/lifx/__init__.py +++ b/homeassistant/components/lifx/__init__.py @@ -17,9 +17,10 @@ from homeassistant.const import ( CONF_HOST, CONF_PORT, EVENT_HOMEASSISTANT_STARTED, + EVENT_HOMEASSISTANT_STOP, Platform, ) -from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback +from homeassistant.core import CALLBACK_TYPE, Event, HomeAssistant, callback from homeassistant.exceptions import ConfigEntryNotReady import homeassistant.helpers.config_validation as cv from homeassistant.helpers.event import async_call_later, async_track_time_interval @@ -163,7 +164,15 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: We do not want the discovery task to block startup. """ - asyncio.create_task(discovery_manager.async_discovery()) + task = asyncio.create_task(discovery_manager.async_discovery()) + + @callback + def _async_stop(_: Event) -> None: + if not task.done(): + task.cancel() + + # Task must be shut down when home assistant is closing + hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, _async_stop) # Let the system settle a bit before starting discovery # to reduce the risk we miss devices because the event diff --git a/tests/components/automation/test_init.py b/tests/components/automation/test_init.py index 742ae85ed68..1ce6cb616da 100644 --- a/tests/components/automation/test_init.py +++ b/tests/components/automation/test_init.py @@ -2140,12 +2140,12 @@ async def test_recursive_automation_starting_script( hass.bus.async_listen("automation_triggered", async_automation_triggered) hass.bus.async_fire("trigger_automation") - await asyncio.wait_for(script_done_event.wait(), 1) + await asyncio.wait_for(script_done_event.wait(), 10) # Trigger 1st stage script shutdown hass.state = CoreState.stopping hass.bus.async_fire("homeassistant_stop") - await asyncio.wait_for(stop_scripts_at_shutdown_called.wait(), 1) + await asyncio.wait_for(stop_scripts_at_shutdown_called.wait(), 10) # Trigger 2nd stage script shutdown async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=60)) diff --git a/tests/components/emulated_hue/test_init.py b/tests/components/emulated_hue/test_init.py index 408a44cda00..cfe4dd3a7bb 100644 --- a/tests/components/emulated_hue/test_init.py +++ b/tests/components/emulated_hue/test_init.py @@ -8,6 +8,7 @@ from homeassistant.components.emulated_hue.config import ( SAVE_DELAY, Config, ) +from homeassistant.components.emulated_hue.upnp import UPNPResponderProtocol from homeassistant.const import EVENT_HOMEASSISTANT_START from homeassistant.setup import async_setup_component from homeassistant.util import utcnow @@ -127,6 +128,9 @@ async def test_setup_works(hass): ) as mock_create_upnp_datagram_endpoint, patch( "homeassistant.components.emulated_hue.async_get_source_ip" ): + mock_create_upnp_datagram_endpoint.return_value = AsyncMock( + spec=UPNPResponderProtocol + ) assert await async_setup_component(hass, "emulated_hue", {}) hass.bus.async_fire(EVENT_HOMEASSISTANT_START) await hass.async_block_till_done() diff --git a/tests/components/modbus/test_init.py b/tests/components/modbus/test_init.py index e238ecc6170..73b1f9743c2 100644 --- a/tests/components/modbus/test_init.py +++ b/tests/components/modbus/test_init.py @@ -529,7 +529,7 @@ async def test_pb_service_write( data[do_write[DATA]], ) if do_return[DATA]: - assert caplog.messages[-1].startswith("Pymodbus:") + assert any(message.startswith("Pymodbus:") for message in caplog.messages) @pytest.fixture(name="mock_modbus_read_pymodbus") diff --git a/tests/components/modem_callerid/test_init.py b/tests/components/modem_callerid/test_init.py index 0465fb24a07..de49e229ef1 100644 --- a/tests/components/modem_callerid/test_init.py +++ b/tests/components/modem_callerid/test_init.py @@ -1,5 +1,5 @@ """Test Modem Caller ID integration.""" -from unittest.mock import AsyncMock, patch +from unittest.mock import patch from phone_modem import exceptions @@ -20,7 +20,7 @@ async def test_setup_entry(hass: HomeAssistant): data={CONF_DEVICE: com_port().device}, ) entry.add_to_hass(hass) - with patch("aioserial.AioSerial", return_value=AsyncMock()), patch( + with patch("aioserial.AioSerial", autospec=True), patch( "homeassistant.components.modem_callerid.PhoneModem._get_response", return_value="OK", ), patch("phone_modem.PhoneModem._modem_sm"): diff --git a/tests/components/withings/test_init.py b/tests/components/withings/test_init.py index 83e8a622e78..70c4d177e59 100644 --- a/tests/components/withings/test_init.py +++ b/tests/components/withings/test_init.py @@ -177,6 +177,10 @@ async def test_set_config_unique_id( spec=DataUpdateCoordinator ) data_manager.poll_data_update_coordinator.last_update_success = True + data_manager.subscription_update_coordinator = MagicMock( + spec=DataUpdateCoordinator + ) + data_manager.subscription_update_coordinator.last_update_success = True mock.return_value = data_manager config_entry.add_to_hass(hass)