From 6f357cb23eca0a0be2729416dad5ae40c99f36b4 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 12 Aug 2019 07:42:12 -0700 Subject: [PATCH] First pass fixing tests that raise exceptions caught by asyncio.gather (#25860) * First pass fixing tests that raise exceptions caught by asyncio.gather * Fix demo test * lint --- homeassistant/components/demo/__init__.py | 11 ++++++++-- homeassistant/components/roomba/vacuum.py | 2 +- homeassistant/components/vacuum/__init__.py | 20 +++++++++++++++++++ homeassistant/config.py | 3 ++- tests/common.py | 2 ++ tests/components/alexa/test_state_report.py | 2 +- tests/components/axis/test_config_flow.py | 8 ++++++++ tests/components/cloud/test_alexa_config.py | 13 ++++++------ tests/components/deconz/test_binary_sensor.py | 1 + tests/components/deconz/test_climate.py | 1 + tests/components/deconz/test_cover.py | 1 + tests/components/deconz/test_light.py | 1 + tests/components/deconz/test_sensor.py | 1 + tests/components/deconz/test_switch.py | 1 + .../components/homematicip_cloud/test_init.py | 16 +++++++++++++-- .../smartthings/test_config_flow.py | 2 ++ tests/components/smartthings/test_init.py | 3 +++ tests/components/upnp/test_init.py | 5 ++++- 18 files changed, 79 insertions(+), 14 deletions(-) diff --git a/homeassistant/components/demo/__init__.py b/homeassistant/components/demo/__init__.py index f8b61167ef7..967b7852c6f 100644 --- a/homeassistant/components/demo/__init__.py +++ b/homeassistant/components/demo/__init__.py @@ -176,8 +176,15 @@ async def async_setup(hass, config): async def finish_setup(hass, config): """Finish set up once demo platforms are set up.""" - lights = sorted(hass.states.async_entity_ids("light")) - switches = sorted(hass.states.async_entity_ids("switch")) + switches = None + lights = None + + while not switches and not lights: + # Not all platforms might be loaded. + if switches is not None: + await asyncio.sleep(0) + switches = sorted(hass.states.async_entity_ids("switch")) + lights = sorted(hass.states.async_entity_ids("light")) # Set up history graph await bootstrap.async_setup_component( diff --git a/homeassistant/components/roomba/vacuum.py b/homeassistant/components/roomba/vacuum.py index ba202c4ad9e..766fd72cdba 100644 --- a/homeassistant/components/roomba/vacuum.py +++ b/homeassistant/components/roomba/vacuum.py @@ -199,7 +199,7 @@ class RoombaVacuum(VacuumDevice): await self.hass.async_add_job(self.vacuum.send_command, "resume") self._is_on = True - async def async_pause(self, **kwargs): + async def async_pause(self): """Pause the cleaning cycle.""" await self.hass.async_add_job(self.vacuum.send_command, "pause") self._is_on = False diff --git a/homeassistant/components/vacuum/__init__.py b/homeassistant/components/vacuum/__init__.py index 598c068aad5..9bc376916c6 100644 --- a/homeassistant/components/vacuum/__init__.py +++ b/homeassistant/components/vacuum/__init__.py @@ -324,6 +324,14 @@ class VacuumDevice(_BaseVacuum, ToggleEntity): """ await self.hass.async_add_executor_job(partial(self.start_pause, **kwargs)) + async def async_pause(self): + """Not supported.""" + pass + + async def async_start(self): + """Not supported.""" + pass + class StateVacuumDevice(_BaseVacuum): """Representation of a vacuum cleaner robot that supports states.""" @@ -378,3 +386,15 @@ class StateVacuumDevice(_BaseVacuum): This method must be run in the event loop. """ await self.hass.async_add_executor_job(self.pause) + + async def async_turn_on(self, **kwargs): + """Not supported.""" + pass + + async def async_turn_off(self, **kwargs): + """Not supported.""" + pass + + async def async_toggle(self, **kwargs): + """Not supported.""" + pass diff --git a/homeassistant/config.py b/homeassistant/config.py index ccf1317e660..1f42b3db25e 100644 --- a/homeassistant/config.py +++ b/homeassistant/config.py @@ -322,7 +322,8 @@ async def async_hass_config_yaml(hass: HomeAssistant) -> Dict: config = load_yaml_config_file(path) return config - config = await hass.async_add_executor_job(_load_hass_yaml_config) + # Not using async_add_executor_job because this is an internal method. + config = await hass.loop.run_in_executor(None, _load_hass_yaml_config) core_config = config.get(CONF_CORE, {}) await merge_packages_config(hass, config, core_config.get(CONF_PACKAGES, {})) return config diff --git a/tests/common.py b/tests/common.py index 3ca4046db85..a139ca83743 100644 --- a/tests/common.py +++ b/tests/common.py @@ -971,6 +971,8 @@ async def flush_store(store): if store._data is None: return + store._async_cleanup_stop_listener() + store._async_cleanup_delay_listener() await store._async_handle_write_data() diff --git a/tests/components/alexa/test_state_report.py b/tests/components/alexa/test_state_report.py index 9f745792e59..f6bb4c9cc29 100644 --- a/tests/components/alexa/test_state_report.py +++ b/tests/components/alexa/test_state_report.py @@ -5,7 +5,7 @@ from . import TEST_URL, DEFAULT_CONFIG async def test_report_state(hass, aioclient_mock): """Test proactive state reports.""" - aioclient_mock.post(TEST_URL, json={"data": "is irrelevant"}) + aioclient_mock.post(TEST_URL, json={"data": "is irrelevant"}, status=202) hass.states.async_set( "binary_sensor.test_contact", diff --git a/tests/components/axis/test_config_flow.py b/tests/components/axis/test_config_flow.py index a7d67e39f44..5ec3f933e9e 100644 --- a/tests/components/axis/test_config_flow.py +++ b/tests/components/axis/test_config_flow.py @@ -39,6 +39,8 @@ async def test_flow_works(hass): mock_device.side_effect = mock_constructor mock_device.vapix.params.system_serialnumber = "serialnumber" mock_device.vapix.params.prodnbr = "prodnbr" + mock_device.vapix.params.prodtype = "prodtype" + mock_device.vapix.params.firmware_version = "firmware_version" result = await hass.config_entries.flow.async_init( config_flow.DOMAIN, context={"source": "user"} @@ -220,6 +222,10 @@ async def test_zeroconf_flow_known_device(hass): return mock_device mock_device.side_effect = mock_constructor + mock_device.vapix.params.system_serialnumber = "serialnumber" + mock_device.vapix.params.prodnbr = "prodnbr" + mock_device.vapix.params.prodtype = "prodtype" + mock_device.vapix.params.firmware_version = "firmware_version" result = await hass.config_entries.flow.async_init( config_flow.DOMAIN, @@ -338,6 +344,8 @@ async def test_import_flow_works(hass): mock_device.side_effect = mock_constructor mock_device.vapix.params.system_serialnumber = "serialnumber" mock_device.vapix.params.prodnbr = "prodnbr" + mock_device.vapix.params.prodtype = "prodtype" + mock_device.vapix.params.firmware_version = "firmware_version" result = await hass.config_entries.flow.async_init( config_flow.DOMAIN, diff --git a/tests/components/cloud/test_alexa_config.py b/tests/components/cloud/test_alexa_config.py index 688d69c16f1..22d8c64c3b0 100644 --- a/tests/components/cloud/test_alexa_config.py +++ b/tests/components/cloud/test_alexa_config.py @@ -52,16 +52,17 @@ def patch_sync_helper(): to_update = [] to_remove = [] + async def sync_helper(to_upd, to_rem): + to_update.extend([ent_id for ent_id in to_upd if ent_id not in to_update]) + to_remove.extend([ent_id for ent_id in to_rem if ent_id not in to_remove]) + return True + with patch("homeassistant.components.cloud.alexa_config.SYNC_DELAY", 0), patch( "homeassistant.components.cloud.alexa_config.AlexaConfig._sync_helper", - side_effect=mock_coro, - ) as mock_helper: + side_effect=sync_helper, + ): yield to_update, to_remove - actual_to_update, actual_to_remove = mock_helper.mock_calls[0][1] - to_update.extend(actual_to_update) - to_remove.extend(actual_to_remove) - async def test_alexa_update_expose_trigger_sync(hass, cloud_prefs): """Test Alexa config responds to updating exposed entities.""" diff --git a/tests/components/deconz/test_binary_sensor.py b/tests/components/deconz/test_binary_sensor.py index 9eb408ba4f1..9e6d4f571ea 100644 --- a/tests/components/deconz/test_binary_sensor.py +++ b/tests/components/deconz/test_binary_sensor.py @@ -115,6 +115,7 @@ async def test_add_new_sensor(hass): sensor.name = "name" sensor.type = "ZHAPresence" sensor.BINARY = True + sensor.uniqueid = "1" sensor.register_async_callback = Mock() async_dispatcher_send(hass, gateway.async_event_new_device("sensor"), [sensor]) await hass.async_block_till_done() diff --git a/tests/components/deconz/test_climate.py b/tests/components/deconz/test_climate.py index 264c3b8761f..68d1957f97e 100644 --- a/tests/components/deconz/test_climate.py +++ b/tests/components/deconz/test_climate.py @@ -178,6 +178,7 @@ async def test_add_new_climate_device(hass): sensor = Mock() sensor.name = "name" sensor.type = "ZHAThermostat" + sensor.uniqueid = "1" sensor.register_async_callback = Mock() async_dispatcher_send(hass, gateway.async_event_new_device("sensor"), [sensor]) await hass.async_block_till_done() diff --git a/tests/components/deconz/test_cover.py b/tests/components/deconz/test_cover.py index c6f3a4b12c8..ee68744f999 100644 --- a/tests/components/deconz/test_cover.py +++ b/tests/components/deconz/test_cover.py @@ -132,6 +132,7 @@ async def test_add_new_cover(hass): cover = Mock() cover.name = "name" cover.type = "Level controllable output" + cover.uniqueid = "1" cover.register_async_callback = Mock() async_dispatcher_send(hass, gateway.async_event_new_device("light"), [cover]) await hass.async_block_till_done() diff --git a/tests/components/deconz/test_light.py b/tests/components/deconz/test_light.py index 77e983e34b4..ee81e476a12 100644 --- a/tests/components/deconz/test_light.py +++ b/tests/components/deconz/test_light.py @@ -190,6 +190,7 @@ async def test_add_new_light(hass): gateway = await setup_gateway(hass, {}) light = Mock() light.name = "name" + light.uniqueid = "1" light.register_async_callback = Mock() async_dispatcher_send(hass, gateway.async_event_new_device("light"), [light]) await hass.async_block_till_done() diff --git a/tests/components/deconz/test_sensor.py b/tests/components/deconz/test_sensor.py index 9c03f3e9a90..21efd768be2 100644 --- a/tests/components/deconz/test_sensor.py +++ b/tests/components/deconz/test_sensor.py @@ -158,6 +158,7 @@ async def test_add_new_sensor(hass): sensor = Mock() sensor.name = "name" sensor.type = "ZHATemperature" + sensor.uniqueid = "1" sensor.BINARY = False sensor.register_async_callback = Mock() async_dispatcher_send(hass, gateway.async_event_new_device("sensor"), [sensor]) diff --git a/tests/components/deconz/test_switch.py b/tests/components/deconz/test_switch.py index 8275e91ecf9..433386a1751 100644 --- a/tests/components/deconz/test_switch.py +++ b/tests/components/deconz/test_switch.py @@ -140,6 +140,7 @@ async def test_add_new_switch(hass): switch = Mock() switch.name = "name" switch.type = "Smart plug" + switch.uniqueid = "1" switch.register_async_callback = Mock() async_dispatcher_send(hass, gateway.async_event_new_device("light"), [switch]) await hass.async_block_till_done() diff --git a/tests/components/homematicip_cloud/test_init.py b/tests/components/homematicip_cloud/test_init.py index 5d160108eb5..d77d4a7e5b2 100644 --- a/tests/components/homematicip_cloud/test_init.py +++ b/tests/components/homematicip_cloud/test_init.py @@ -68,7 +68,13 @@ async def test_setup_entry_successful(hass): ) entry.add_to_hass(hass) with patch.object(hmipc, "HomematicipHAP") as mock_hap: - mock_hap.return_value.async_setup.return_value = mock_coro(True) + instance = mock_hap.return_value + instance.async_setup.return_value = mock_coro(True) + instance.home.id = "1" + instance.home.modelType = "mock-type" + instance.home.name = "mock-name" + instance.home.currentAPVersion = "mock-ap-version" + assert ( await async_setup_component( hass, @@ -129,7 +135,13 @@ async def test_unload_entry(hass): entry.add_to_hass(hass) with patch.object(hmipc, "HomematicipHAP") as mock_hap: - mock_hap.return_value.async_setup.return_value = mock_coro(True) + instance = mock_hap.return_value + instance.async_setup.return_value = mock_coro(True) + instance.home.id = "1" + instance.home.modelType = "mock-type" + instance.home.name = "mock-name" + instance.home.currentAPVersion = "mock-ap-version" + assert await async_setup_component(hass, hmipc.DOMAIN, {}) is True assert len(mock_hap.return_value.mock_calls) >= 1 diff --git a/tests/components/smartthings/test_config_flow.py b/tests/components/smartthings/test_config_flow.py index 0ff4b08c750..5724d7a3bac 100644 --- a/tests/components/smartthings/test_config_flow.py +++ b/tests/components/smartthings/test_config_flow.py @@ -6,6 +6,7 @@ from asynctest import Mock, patch from pysmartthings import APIResponseError from homeassistant import data_entry_flow +from homeassistant.setup import async_setup_component from homeassistant.components import cloud from homeassistant.components.smartthings import smartapp from homeassistant.components.smartthings.config_flow import SmartThingsFlowHandler @@ -288,6 +289,7 @@ async def test_multiple_config_entry_created_when_installed( hass, app, locations, installed_apps, smartthings_mock ): """Test a config entries are created for multiple installs.""" + assert await async_setup_component(hass, "persistent_notification", {}) flow = SmartThingsFlowHandler() flow.hass = hass flow.access_token = str(uuid4()) diff --git a/tests/components/smartthings/test_init.py b/tests/components/smartthings/test_init.py index 881be3b992d..15b556f1d83 100644 --- a/tests/components/smartthings/test_init.py +++ b/tests/components/smartthings/test_init.py @@ -6,6 +6,7 @@ from asynctest import Mock, patch from pysmartthings import InstalledAppStatus, OAuthToken import pytest +from homeassistant.setup import async_setup_component from homeassistant.components import cloud, smartthings from homeassistant.components.smartthings.const import ( CONF_CLOUDHOOK_URL, @@ -25,6 +26,7 @@ from tests.common import MockConfigEntry async def test_migration_creates_new_flow(hass, smartthings_mock, config_entry): """Test migration deletes app and creates new flow.""" + assert await async_setup_component(hass, "persistent_notification", {}) config_entry.version = 1 config_entry.add_to_hass(hass) @@ -50,6 +52,7 @@ async def test_unrecoverable_api_errors_create_new_flow( 403 (forbidden/not found): Occurs when the app or installed app could not be retrieved/found (likely deleted?) """ + assert await async_setup_component(hass, "persistent_notification", {}) config_entry.add_to_hass(hass) smartthings_mock.app.side_effect = ClientResponseError(None, None, status=401) diff --git a/tests/components/upnp/test_init.py b/tests/components/upnp/test_init.py index a5b1c04cb35..5f17606146b 100644 --- a/tests/components/upnp/test_init.py +++ b/tests/components/upnp/test_init.py @@ -18,7 +18,10 @@ class MockDevice(Device): def __init__(self, udn): """Initializer.""" - super().__init__(MagicMock()) + device = MagicMock() + device.manufacturer = "mock-manuf" + device.name = "mock-name" + super().__init__(device) self._udn = udn self.added_port_mappings = [] self.removed_port_mappings = []