From 60bc517d011d26b43f121243a3de9a2683762f76 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Tue, 7 Apr 2020 18:33:23 +0200 Subject: [PATCH] Collection of core tests improvements (#33757) * Collection of core tests improvements * Added some more * Fix aiohttp client response release --- tests/helpers/test_aiohttp_client.py | 175 +++++++++--------------- tests/helpers/test_dispatcher.py | 192 +++++++++++++-------------- tests/helpers/test_entity.py | 80 +++++------ tests/helpers/test_event.py | 40 +++--- tests/helpers/test_service.py | 12 +- tests/helpers/test_state.py | 8 +- tests/test_bootstrap.py | 6 +- tests/test_config.py | 6 +- tests/test_config_entries.py | 74 ++++++++--- tests/test_setup.py | 21 +-- tests/test_util/aiohttp.py | 19 +-- tests/util/test_logging.py | 12 +- 12 files changed, 302 insertions(+), 343 deletions(-) diff --git a/tests/helpers/test_aiohttp_client.py b/tests/helpers/test_aiohttp_client.py index de7057ae9c7..aabc71ca9d8 100644 --- a/tests/helpers/test_aiohttp_client.py +++ b/tests/helpers/test_aiohttp_client.py @@ -1,6 +1,5 @@ """Test the aiohttp client helper.""" import asyncio -import unittest import aiohttp import pytest @@ -8,9 +7,6 @@ import pytest from homeassistant.core import EVENT_HOMEASSISTANT_CLOSE import homeassistant.helpers.aiohttp_client as client from homeassistant.setup import async_setup_component -from homeassistant.util.async_ import run_callback_threadsafe - -from tests.common import get_test_home_assistant @pytest.fixture @@ -33,130 +29,91 @@ def camera_client(hass, hass_client): yield hass.loop.run_until_complete(hass_client()) -class TestHelpersAiohttpClient(unittest.TestCase): - """Test homeassistant.helpers.aiohttp_client module.""" +async def test_get_clientsession_with_ssl(hass): + """Test init clientsession with ssl.""" + client.async_get_clientsession(hass) - def setup_method(self, method): - """Set up things to be run when tests are started.""" - self.hass = get_test_home_assistant() - - def teardown_method(self, method): - """Stop everything that was started.""" - self.hass.stop() - - def test_get_clientsession_with_ssl(self): - """Test init clientsession with ssl.""" - run_callback_threadsafe( - self.hass.loop, client.async_get_clientsession, self.hass - ).result() - - assert isinstance( - self.hass.data[client.DATA_CLIENTSESSION], aiohttp.ClientSession - ) - assert isinstance(self.hass.data[client.DATA_CONNECTOR], aiohttp.TCPConnector) - - def test_get_clientsession_without_ssl(self): - """Test init clientsession without ssl.""" - run_callback_threadsafe( - self.hass.loop, client.async_get_clientsession, self.hass, False - ).result() - - assert isinstance( - self.hass.data[client.DATA_CLIENTSESSION_NOTVERIFY], aiohttp.ClientSession - ) - assert isinstance( - self.hass.data[client.DATA_CONNECTOR_NOTVERIFY], aiohttp.TCPConnector - ) - - def test_create_clientsession_with_ssl_and_cookies(self): - """Test create clientsession with ssl.""" - - def _async_helper(): - return client.async_create_clientsession(self.hass, cookies={"bla": True}) - - session = run_callback_threadsafe(self.hass.loop, _async_helper).result() - - assert isinstance(session, aiohttp.ClientSession) - assert isinstance(self.hass.data[client.DATA_CONNECTOR], aiohttp.TCPConnector) - - def test_create_clientsession_without_ssl_and_cookies(self): - """Test create clientsession without ssl.""" - - def _async_helper(): - return client.async_create_clientsession( - self.hass, False, cookies={"bla": True} - ) - - session = run_callback_threadsafe(self.hass.loop, _async_helper).result() - - assert isinstance(session, aiohttp.ClientSession) - assert isinstance( - self.hass.data[client.DATA_CONNECTOR_NOTVERIFY], aiohttp.TCPConnector - ) - - def test_get_clientsession_cleanup(self): - """Test init clientsession with ssl.""" - run_callback_threadsafe( - self.hass.loop, client.async_get_clientsession, self.hass - ).result() - - assert isinstance( - self.hass.data[client.DATA_CLIENTSESSION], aiohttp.ClientSession - ) - assert isinstance(self.hass.data[client.DATA_CONNECTOR], aiohttp.TCPConnector) - - self.hass.bus.fire(EVENT_HOMEASSISTANT_CLOSE) - self.hass.block_till_done() - - assert self.hass.data[client.DATA_CLIENTSESSION].closed - assert self.hass.data[client.DATA_CONNECTOR].closed - - def test_get_clientsession_cleanup_without_ssl(self): - """Test init clientsession with ssl.""" - run_callback_threadsafe( - self.hass.loop, client.async_get_clientsession, self.hass, False - ).result() - - assert isinstance( - self.hass.data[client.DATA_CLIENTSESSION_NOTVERIFY], aiohttp.ClientSession - ) - assert isinstance( - self.hass.data[client.DATA_CONNECTOR_NOTVERIFY], aiohttp.TCPConnector - ) - - self.hass.bus.fire(EVENT_HOMEASSISTANT_CLOSE) - self.hass.block_till_done() - - assert self.hass.data[client.DATA_CLIENTSESSION_NOTVERIFY].closed - assert self.hass.data[client.DATA_CONNECTOR_NOTVERIFY].closed + assert isinstance(hass.data[client.DATA_CLIENTSESSION], aiohttp.ClientSession) + assert isinstance(hass.data[client.DATA_CONNECTOR], aiohttp.TCPConnector) -@asyncio.coroutine -def test_async_aiohttp_proxy_stream(aioclient_mock, camera_client): +async def test_get_clientsession_without_ssl(hass): + """Test init clientsession without ssl.""" + client.async_get_clientsession(hass, verify_ssl=False) + + assert isinstance( + hass.data[client.DATA_CLIENTSESSION_NOTVERIFY], aiohttp.ClientSession + ) + assert isinstance(hass.data[client.DATA_CONNECTOR_NOTVERIFY], aiohttp.TCPConnector) + + +async def test_create_clientsession_with_ssl_and_cookies(hass): + """Test create clientsession with ssl.""" + session = client.async_create_clientsession(hass, cookies={"bla": True}) + assert isinstance(session, aiohttp.ClientSession) + assert isinstance(hass.data[client.DATA_CONNECTOR], aiohttp.TCPConnector) + + +async def test_create_clientsession_without_ssl_and_cookies(hass): + """Test create clientsession without ssl.""" + session = client.async_create_clientsession(hass, False, cookies={"bla": True}) + assert isinstance(session, aiohttp.ClientSession) + assert isinstance(hass.data[client.DATA_CONNECTOR_NOTVERIFY], aiohttp.TCPConnector) + + +async def test_get_clientsession_cleanup(hass): + """Test init clientsession with ssl.""" + client.async_get_clientsession(hass) + + assert isinstance(hass.data[client.DATA_CLIENTSESSION], aiohttp.ClientSession) + assert isinstance(hass.data[client.DATA_CONNECTOR], aiohttp.TCPConnector) + + hass.bus.async_fire(EVENT_HOMEASSISTANT_CLOSE) + await hass.async_block_till_done() + + assert hass.data[client.DATA_CLIENTSESSION].closed + assert hass.data[client.DATA_CONNECTOR].closed + + +async def test_get_clientsession_cleanup_without_ssl(hass): + """Test init clientsession with ssl.""" + client.async_get_clientsession(hass, verify_ssl=False) + + assert isinstance( + hass.data[client.DATA_CLIENTSESSION_NOTVERIFY], aiohttp.ClientSession + ) + assert isinstance(hass.data[client.DATA_CONNECTOR_NOTVERIFY], aiohttp.TCPConnector) + + hass.bus.async_fire(EVENT_HOMEASSISTANT_CLOSE) + await hass.async_block_till_done() + + assert hass.data[client.DATA_CLIENTSESSION_NOTVERIFY].closed + assert hass.data[client.DATA_CONNECTOR_NOTVERIFY].closed + + +async def test_async_aiohttp_proxy_stream(aioclient_mock, camera_client): """Test that it fetches the given url.""" aioclient_mock.get("http://example.com/mjpeg_stream", content=b"Frame1Frame2Frame3") - resp = yield from camera_client.get("/api/camera_proxy_stream/camera.config_test") + resp = await camera_client.get("/api/camera_proxy_stream/camera.config_test") assert resp.status == 200 assert aioclient_mock.call_count == 1 - body = yield from resp.text() + body = await resp.text() assert body == "Frame1Frame2Frame3" -@asyncio.coroutine -def test_async_aiohttp_proxy_stream_timeout(aioclient_mock, camera_client): +async def test_async_aiohttp_proxy_stream_timeout(aioclient_mock, camera_client): """Test that it fetches the given url.""" aioclient_mock.get("http://example.com/mjpeg_stream", exc=asyncio.TimeoutError()) - resp = yield from camera_client.get("/api/camera_proxy_stream/camera.config_test") + resp = await camera_client.get("/api/camera_proxy_stream/camera.config_test") assert resp.status == 504 -@asyncio.coroutine -def test_async_aiohttp_proxy_stream_client_err(aioclient_mock, camera_client): +async def test_async_aiohttp_proxy_stream_client_err(aioclient_mock, camera_client): """Test that it fetches the given url.""" aioclient_mock.get("http://example.com/mjpeg_stream", exc=aiohttp.ClientError()) - resp = yield from camera_client.get("/api/camera_proxy_stream/camera.config_test") + resp = await camera_client.get("/api/camera_proxy_stream/camera.config_test") assert resp.status == 502 diff --git a/tests/helpers/test_dispatcher.py b/tests/helpers/test_dispatcher.py index 539d9ad1651..d2aa939043c 100644 --- a/tests/helpers/test_dispatcher.py +++ b/tests/helpers/test_dispatcher.py @@ -1,143 +1,131 @@ """Test dispatcher helpers.""" -import asyncio from functools import partial from homeassistant.core import callback from homeassistant.helpers.dispatcher import ( async_dispatcher_connect, - dispatcher_connect, - dispatcher_send, + async_dispatcher_send, ) -from tests.common import get_test_home_assistant + +async def test_simple_function(hass): + """Test simple function (executor).""" + calls = [] + + def test_funct(data): + """Test function.""" + calls.append(data) + + async_dispatcher_connect(hass, "test", test_funct) + async_dispatcher_send(hass, "test", 3) + await hass.async_block_till_done() + + assert calls == [3] + + async_dispatcher_send(hass, "test", "bla") + await hass.async_block_till_done() + + assert calls == [3, "bla"] -class TestHelpersDispatcher: - """Tests for discovery helper methods.""" +async def test_simple_function_unsub(hass): + """Test simple function (executor) and unsub.""" + calls1 = [] + calls2 = [] - def setup_method(self, method): - """Set up things to be run when tests are started.""" - self.hass = get_test_home_assistant() + def test_funct1(data): + """Test function.""" + calls1.append(data) - def teardown_method(self, method): - """Stop everything that was started.""" - self.hass.stop() + def test_funct2(data): + """Test function.""" + calls2.append(data) - def test_simple_function(self): - """Test simple function (executor).""" - calls = [] + async_dispatcher_connect(hass, "test1", test_funct1) + unsub = async_dispatcher_connect(hass, "test2", test_funct2) + async_dispatcher_send(hass, "test1", 3) + async_dispatcher_send(hass, "test2", 4) + await hass.async_block_till_done() - def test_funct(data): - """Test function.""" - calls.append(data) + assert calls1 == [3] + assert calls2 == [4] - dispatcher_connect(self.hass, "test", test_funct) - dispatcher_send(self.hass, "test", 3) - self.hass.block_till_done() + unsub() - assert calls == [3] + async_dispatcher_send(hass, "test1", 5) + async_dispatcher_send(hass, "test2", 6) + await hass.async_block_till_done() - dispatcher_send(self.hass, "test", "bla") - self.hass.block_till_done() + assert calls1 == [3, 5] + assert calls2 == [4] - assert calls == [3, "bla"] + # check don't kill the flow + unsub() - def test_simple_function_unsub(self): - """Test simple function (executor) and unsub.""" - calls1 = [] - calls2 = [] + async_dispatcher_send(hass, "test1", 7) + async_dispatcher_send(hass, "test2", 8) + await hass.async_block_till_done() - def test_funct1(data): - """Test function.""" - calls1.append(data) + assert calls1 == [3, 5, 7] + assert calls2 == [4] - def test_funct2(data): - """Test function.""" - calls2.append(data) - dispatcher_connect(self.hass, "test1", test_funct1) - unsub = dispatcher_connect(self.hass, "test2", test_funct2) - dispatcher_send(self.hass, "test1", 3) - dispatcher_send(self.hass, "test2", 4) - self.hass.block_till_done() +async def test_simple_callback(hass): + """Test simple callback (async).""" + calls = [] - assert calls1 == [3] - assert calls2 == [4] + @callback + def test_funct(data): + """Test function.""" + calls.append(data) - unsub() + async_dispatcher_connect(hass, "test", test_funct) + async_dispatcher_send(hass, "test", 3) + await hass.async_block_till_done() - dispatcher_send(self.hass, "test1", 5) - dispatcher_send(self.hass, "test2", 6) - self.hass.block_till_done() + assert calls == [3] - assert calls1 == [3, 5] - assert calls2 == [4] + async_dispatcher_send(hass, "test", "bla") + await hass.async_block_till_done() - # check don't kill the flow - unsub() + assert calls == [3, "bla"] - dispatcher_send(self.hass, "test1", 7) - dispatcher_send(self.hass, "test2", 8) - self.hass.block_till_done() - assert calls1 == [3, 5, 7] - assert calls2 == [4] +async def test_simple_coro(hass): + """Test simple coro (async).""" + calls = [] - def test_simple_callback(self): - """Test simple callback (async).""" - calls = [] + async def async_test_funct(data): + """Test function.""" + calls.append(data) - @callback - def test_funct(data): - """Test function.""" - calls.append(data) + async_dispatcher_connect(hass, "test", async_test_funct) + async_dispatcher_send(hass, "test", 3) + await hass.async_block_till_done() - dispatcher_connect(self.hass, "test", test_funct) - dispatcher_send(self.hass, "test", 3) - self.hass.block_till_done() + assert calls == [3] - assert calls == [3] + async_dispatcher_send(hass, "test", "bla") + await hass.async_block_till_done() - dispatcher_send(self.hass, "test", "bla") - self.hass.block_till_done() + assert calls == [3, "bla"] - assert calls == [3, "bla"] - def test_simple_coro(self): - """Test simple coro (async).""" - calls = [] +async def test_simple_function_multiargs(hass): + """Test simple function (executor).""" + calls = [] - @asyncio.coroutine - def test_funct(data): - """Test function.""" - calls.append(data) + def test_funct(data1, data2, data3): + """Test function.""" + calls.append(data1) + calls.append(data2) + calls.append(data3) - dispatcher_connect(self.hass, "test", test_funct) - dispatcher_send(self.hass, "test", 3) - self.hass.block_till_done() + async_dispatcher_connect(hass, "test", test_funct) + async_dispatcher_send(hass, "test", 3, 2, "bla") + await hass.async_block_till_done() - assert calls == [3] - - dispatcher_send(self.hass, "test", "bla") - self.hass.block_till_done() - - assert calls == [3, "bla"] - - def test_simple_function_multiargs(self): - """Test simple function (executor).""" - calls = [] - - def test_funct(data1, data2, data3): - """Test function.""" - calls.append(data1) - calls.append(data2) - calls.append(data3) - - dispatcher_connect(self.hass, "test", test_funct) - dispatcher_send(self.hass, "test", 3, 2, "bla") - self.hass.block_till_done() - - assert calls == [3, 2, "bla"] + assert calls == [3, 2, "bla"] async def test_callback_exception_gets_logged(hass, caplog): @@ -150,7 +138,7 @@ async def test_callback_exception_gets_logged(hass, caplog): # wrap in partial to test message logging. async_dispatcher_connect(hass, "test", partial(bad_handler)) - dispatcher_send(hass, "test", "bad") + async_dispatcher_send(hass, "test", "bad") await hass.async_block_till_done() await hass.async_block_till_done() diff --git a/tests/helpers/test_entity.py b/tests/helpers/test_entity.py index 6dc194c09d4..dd734bb0dcb 100644 --- a/tests/helpers/test_entity.py +++ b/tests/helpers/test_entity.py @@ -18,55 +18,57 @@ from tests.common import get_test_home_assistant, mock_registry def test_generate_entity_id_requires_hass_or_ids(): """Ensure we require at least hass or current ids.""" - fmt = "test.{}" with pytest.raises(ValueError): - entity.generate_entity_id(fmt, "hello world") + entity.generate_entity_id("test.{}", "hello world") def test_generate_entity_id_given_keys(): """Test generating an entity id given current ids.""" - fmt = "test.{}" assert ( entity.generate_entity_id( - fmt, "overwrite hidden true", current_ids=["test.overwrite_hidden_true"] + "test.{}", + "overwrite hidden true", + current_ids=["test.overwrite_hidden_true"], ) == "test.overwrite_hidden_true_2" ) assert ( entity.generate_entity_id( - fmt, "overwrite hidden true", current_ids=["test.another_entity"] + "test.{}", "overwrite hidden true", current_ids=["test.another_entity"] ) == "test.overwrite_hidden_true" ) -def test_async_update_support(hass): +async def test_async_update_support(hass): """Test async update getting called.""" sync_update = [] async_update = [] class AsyncEntity(entity.Entity): + """A test entity.""" + entity_id = "sensor.test" def update(self): + """Update entity.""" sync_update.append([1]) ent = AsyncEntity() ent.hass = hass - hass.loop.run_until_complete(ent.async_update_ha_state(True)) + await ent.async_update_ha_state(True) assert len(sync_update) == 1 assert len(async_update) == 0 - @asyncio.coroutine - def async_update_func(): + async def async_update_func(): """Async update.""" async_update.append(1) ent.async_update = async_update_func - hass.loop.run_until_complete(ent.async_update_ha_state(True)) + await ent.async_update_ha_state(True) assert len(sync_update) == 1 assert len(async_update) == 1 @@ -123,13 +125,11 @@ class TestHelpersEntity: assert state.attributes.get(ATTR_DEVICE_CLASS) == "test_class" -@asyncio.coroutine -def test_warn_slow_update(hass): +async def test_warn_slow_update(hass): """Warn we log when entity update takes a long time.""" update_call = False - @asyncio.coroutine - def async_update(): + async def async_update(): """Mock async update.""" nonlocal update_call update_call = True @@ -140,7 +140,7 @@ def test_warn_slow_update(hass): mock_entity.async_update = async_update with patch.object(hass.loop, "call_later", MagicMock()) as mock_call: - yield from mock_entity.async_update_ha_state(True) + await mock_entity.async_update_ha_state(True) assert mock_call.called assert len(mock_call.mock_calls) == 2 @@ -154,13 +154,11 @@ def test_warn_slow_update(hass): assert update_call -@asyncio.coroutine -def test_warn_slow_update_with_exception(hass): +async def test_warn_slow_update_with_exception(hass): """Warn we log when entity update takes a long time and trow exception.""" update_call = False - @asyncio.coroutine - def async_update(): + async def async_update(): """Mock async update.""" nonlocal update_call update_call = True @@ -172,7 +170,7 @@ def test_warn_slow_update_with_exception(hass): mock_entity.async_update = async_update with patch.object(hass.loop, "call_later", MagicMock()) as mock_call: - yield from mock_entity.async_update_ha_state(True) + await mock_entity.async_update_ha_state(True) assert mock_call.called assert len(mock_call.mock_calls) == 2 @@ -186,13 +184,11 @@ def test_warn_slow_update_with_exception(hass): assert update_call -@asyncio.coroutine -def test_warn_slow_device_update_disabled(hass): +async def test_warn_slow_device_update_disabled(hass): """Disable slow update warning with async_device_update.""" update_call = False - @asyncio.coroutine - def async_update(): + async def async_update(): """Mock async update.""" nonlocal update_call update_call = True @@ -203,19 +199,17 @@ def test_warn_slow_device_update_disabled(hass): mock_entity.async_update = async_update with patch.object(hass.loop, "call_later", MagicMock()) as mock_call: - yield from mock_entity.async_device_update(warning=False) + await mock_entity.async_device_update(warning=False) assert not mock_call.called assert update_call -@asyncio.coroutine -def test_async_schedule_update_ha_state(hass): +async def test_async_schedule_update_ha_state(hass): """Warn we log when entity update takes a long time and trow exception.""" update_call = False - @asyncio.coroutine - def async_update(): + async def async_update(): """Mock async update.""" nonlocal update_call update_call = True @@ -226,7 +220,7 @@ def test_async_schedule_update_ha_state(hass): mock_entity.async_update = async_update mock_entity.async_schedule_update_ha_state(True) - yield from hass.async_block_till_done() + await hass.async_block_till_done() assert update_call is True @@ -236,6 +230,8 @@ async def test_async_async_request_call_without_lock(hass): updates = [] class AsyncEntity(entity.Entity): + """Test entity.""" + def __init__(self, entity_id): """Initialize Async test entity.""" self.entity_id = entity_id @@ -271,6 +267,8 @@ async def test_async_async_request_call_with_lock(hass): test_semaphore = asyncio.Semaphore(1) class AsyncEntity(entity.Entity): + """Test entity.""" + def __init__(self, entity_id, lock): """Initialize Async test entity.""" self.entity_id = entity_id @@ -319,6 +317,8 @@ async def test_async_parallel_updates_with_zero(hass): test_lock = asyncio.Event() class AsyncEntity(entity.Entity): + """Test entity.""" + def __init__(self, entity_id, count): """Initialize Async test entity.""" self.entity_id = entity_id @@ -354,6 +354,8 @@ async def test_async_parallel_updates_with_zero_on_sync_update(hass): test_lock = threading.Event() class AsyncEntity(entity.Entity): + """Test entity.""" + def __init__(self, entity_id, count): """Initialize Async test entity.""" self.entity_id = entity_id @@ -393,6 +395,8 @@ async def test_async_parallel_updates_with_one(hass): test_semaphore = asyncio.Semaphore(1) class AsyncEntity(entity.Entity): + """Test entity.""" + def __init__(self, entity_id, count): """Initialize Async test entity.""" self.entity_id = entity_id @@ -467,6 +471,8 @@ async def test_async_parallel_updates_with_two(hass): test_semaphore = asyncio.Semaphore(2) class AsyncEntity(entity.Entity): + """Test entity.""" + def __init__(self, entity_id, count): """Initialize Async test entity.""" self.entity_id = entity_id @@ -474,11 +480,10 @@ async def test_async_parallel_updates_with_two(hass): self._count = count self.parallel_updates = test_semaphore - @asyncio.coroutine - def async_update(self): + async def async_update(self): """Test update.""" updates.append(self._count) - yield from test_lock.acquire() + await test_lock.acquire() ent_1 = AsyncEntity("sensor.test_1", 1) ent_2 = AsyncEntity("sensor.test_2", 2) @@ -529,15 +534,14 @@ async def test_async_parallel_updates_with_two(hass): test_lock.release() -@asyncio.coroutine -def test_async_remove_no_platform(hass): +async def test_async_remove_no_platform(hass): """Test async_remove method when no platform set.""" ent = entity.Entity() ent.hass = hass ent.entity_id = "test.test" - yield from ent.async_update_ha_state() + await ent.async_update_ha_state() assert len(hass.states.async_entity_ids()) == 1 - yield from ent.async_remove() + await ent.async_remove() assert len(hass.states.async_entity_ids()) == 0 @@ -686,6 +690,8 @@ async def test_warn_slow_write_state_custom_component(hass, caplog): """Check that we log a warning if reading properties takes too long.""" class CustomComponentEntity(entity.Entity): + """Custom component entity.""" + __module__ = "custom_components.bla.sensor" mock_entity = CustomComponentEntity() diff --git a/tests/helpers/test_event.py b/tests/helpers/test_event.py index 313710d03b7..f6e375acf0b 100644 --- a/tests/helpers/test_event.py +++ b/tests/helpers/test_event.py @@ -1,6 +1,5 @@ """Test event helpers.""" # pylint: disable=protected-access -import asyncio from datetime import datetime, timedelta from unittest.mock import patch @@ -104,8 +103,7 @@ async def test_track_state_change(hass): async_track_state_change(hass, "light.Bowl", wildcard_run_callback) - @asyncio.coroutine - def wildercard_run_callback(entity_id, old_state, new_state): + async def wildercard_run_callback(entity_id, old_state, new_state): wildercard_runs.append((old_state, new_state)) async_track_state_change(hass, MATCH_ALL, wildercard_run_callback) @@ -189,8 +187,7 @@ async def test_track_template(hass): async_track_template(hass, template_condition, wildcard_run_callback) - @asyncio.coroutine - def wildercard_run_callback(entity_id, old_state, new_state): + async def wildercard_run_callback(entity_id, old_state, new_state): wildercard_runs.append((old_state, new_state)) async_track_template( @@ -263,8 +260,7 @@ async def test_track_same_state_simple_trigger(hass): entity_ids="light.Bowl", ) - @asyncio.coroutine - def coroutine_run_callback(): + async def coroutine_run_callback(): coroutine_runs.append(1) async_track_same_state( @@ -738,27 +734,27 @@ async def test_periodic_task_duplicate_time(hass): async def test_periodic_task_entering_dst(hass): """Test periodic task behavior when entering dst.""" - tz = dt_util.get_time_zone("Europe/Vienna") - dt_util.set_default_time_zone(tz) + timezone = dt_util.get_time_zone("Europe/Vienna") + dt_util.set_default_time_zone(timezone) specific_runs = [] unsub = async_track_time_change( hass, lambda x: specific_runs.append(1), hour=2, minute=30, second=0 ) - _send_time_changed(hass, tz.localize(datetime(2018, 3, 25, 1, 50, 0))) + _send_time_changed(hass, timezone.localize(datetime(2018, 3, 25, 1, 50, 0))) await hass.async_block_till_done() assert len(specific_runs) == 0 - _send_time_changed(hass, tz.localize(datetime(2018, 3, 25, 3, 50, 0))) + _send_time_changed(hass, timezone.localize(datetime(2018, 3, 25, 3, 50, 0))) await hass.async_block_till_done() assert len(specific_runs) == 0 - _send_time_changed(hass, tz.localize(datetime(2018, 3, 26, 1, 50, 0))) + _send_time_changed(hass, timezone.localize(datetime(2018, 3, 26, 1, 50, 0))) await hass.async_block_till_done() assert len(specific_runs) == 0 - _send_time_changed(hass, tz.localize(datetime(2018, 3, 26, 2, 50, 0))) + _send_time_changed(hass, timezone.localize(datetime(2018, 3, 26, 2, 50, 0))) await hass.async_block_till_done() assert len(specific_runs) == 1 @@ -767,29 +763,35 @@ async def test_periodic_task_entering_dst(hass): async def test_periodic_task_leaving_dst(hass): """Test periodic task behavior when leaving dst.""" - tz = dt_util.get_time_zone("Europe/Vienna") - dt_util.set_default_time_zone(tz) + timezone = dt_util.get_time_zone("Europe/Vienna") + dt_util.set_default_time_zone(timezone) specific_runs = [] unsub = async_track_time_change( hass, lambda x: specific_runs.append(1), hour=2, minute=30, second=0 ) - _send_time_changed(hass, tz.localize(datetime(2018, 10, 28, 2, 5, 0), is_dst=False)) + _send_time_changed( + hass, timezone.localize(datetime(2018, 10, 28, 2, 5, 0), is_dst=False) + ) await hass.async_block_till_done() assert len(specific_runs) == 0 _send_time_changed( - hass, tz.localize(datetime(2018, 10, 28, 2, 55, 0), is_dst=False) + hass, timezone.localize(datetime(2018, 10, 28, 2, 55, 0), is_dst=False) ) await hass.async_block_till_done() assert len(specific_runs) == 1 - _send_time_changed(hass, tz.localize(datetime(2018, 10, 28, 2, 5, 0), is_dst=True)) + _send_time_changed( + hass, timezone.localize(datetime(2018, 10, 28, 2, 5, 0), is_dst=True) + ) await hass.async_block_till_done() assert len(specific_runs) == 1 - _send_time_changed(hass, tz.localize(datetime(2018, 10, 28, 2, 55, 0), is_dst=True)) + _send_time_changed( + hass, timezone.localize(datetime(2018, 10, 28, 2, 55, 0), is_dst=True) + ) await hass.async_block_till_done() assert len(specific_runs) == 2 diff --git a/tests/helpers/test_service.py b/tests/helpers/test_service.py index 0f575a7fc54..04d0ec64b83 100644 --- a/tests/helpers/test_service.py +++ b/tests/helpers/test_service.py @@ -1,5 +1,4 @@ """Test service helpers.""" -import asyncio from collections import OrderedDict from copy import deepcopy import unittest @@ -286,13 +285,12 @@ async def test_extract_entity_ids_from_area(hass, area_mock): ) -@asyncio.coroutine -def test_async_get_all_descriptions(hass): +async def test_async_get_all_descriptions(hass): """Test async_get_all_descriptions.""" group = hass.components.group group_config = {group.DOMAIN: {}} - yield from async_setup_component(hass, group.DOMAIN, group_config) - descriptions = yield from service.async_get_all_descriptions(hass) + await async_setup_component(hass, group.DOMAIN, group_config) + descriptions = await service.async_get_all_descriptions(hass) assert len(descriptions) == 1 @@ -301,8 +299,8 @@ def test_async_get_all_descriptions(hass): logger = hass.components.logger logger_config = {logger.DOMAIN: {}} - yield from async_setup_component(hass, logger.DOMAIN, logger_config) - descriptions = yield from service.async_get_all_descriptions(hass) + await async_setup_component(hass, logger.DOMAIN, logger_config) + descriptions = await service.async_get_all_descriptions(hass) assert len(descriptions) == 2 diff --git a/tests/helpers/test_state.py b/tests/helpers/test_state.py index 8a08c06054d..26043c37093 100644 --- a/tests/helpers/test_state.py +++ b/tests/helpers/test_state.py @@ -25,8 +25,7 @@ from homeassistant.util import dt as dt_util from tests.common import async_mock_service -@asyncio.coroutine -def test_async_track_states(hass): +async def test_async_track_states(hass): """Test AsyncTrackStates context manager.""" point1 = dt_util.utcnow() point2 = point1 + timedelta(seconds=5) @@ -50,8 +49,7 @@ def test_async_track_states(hass): assert [state2, state3] == sorted(states, key=lambda state: state.entity_id) -@asyncio.coroutine -def test_call_to_component(hass): +async def test_call_to_component(hass): """Test calls to components state reproduction functions.""" with patch( "homeassistant.components.media_player.reproduce_state.async_reproduce_states" @@ -69,7 +67,7 @@ def test_call_to_component(hass): state_climate = ha.State("climate.test", "bad") context = "dummy_context" - yield from state.async_reproduce_state( + await state.async_reproduce_state( hass, [state_media_player, state_climate], blocking=True, diff --git a/tests/test_bootstrap.py b/tests/test_bootstrap.py index 34704ddfb74..72f26ae33ad 100644 --- a/tests/test_bootstrap.py +++ b/tests/test_bootstrap.py @@ -1,6 +1,5 @@ """Test the bootstrapping.""" # pylint: disable=protected-access -import asyncio import logging import os from unittest.mock import Mock @@ -29,11 +28,10 @@ _LOGGER = logging.getLogger(__name__) @patch("homeassistant.bootstrap.async_enable_logging", Mock()) -@asyncio.coroutine -def test_home_assistant_core_config_validation(hass): +async def test_home_assistant_core_config_validation(hass): """Test if we pass in wrong information for HA conf.""" # Extensive HA conf validation testing is done - result = yield from bootstrap.async_from_config_dict( + result = await bootstrap.async_from_config_dict( {"homeassistant": {"latitude": "some string"}}, hass ) assert result is None diff --git a/tests/test_config.py b/tests/test_config.py index d0d9148f2dd..1d96b3d0625 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -1,6 +1,5 @@ """Test config utils.""" # pylint: disable=protected-access -import asyncio from collections import OrderedDict import copy import os @@ -740,8 +739,7 @@ async def test_merge_duplicate_keys(merge_log_err, hass): assert len(config["input_select"]) == 1 -@asyncio.coroutine -def test_merge_customize(hass): +async def test_merge_customize(hass): """Test loading core config onto hass object.""" core_config = { "latitude": 60, @@ -755,7 +753,7 @@ def test_merge_customize(hass): "pkg1": {"homeassistant": {"customize": {"b.b": {"friendly_name": "BB"}}}} }, } - yield from config_util.async_process_ha_core_config(hass, core_config) + await config_util.async_process_ha_core_config(hass, core_config) assert hass.data[config_util.DATA_CUSTOMIZE].get("b.b") == {"friendly_name": "BB"} diff --git a/tests/test_config_entries.py b/tests/test_config_entries.py index 17494b6b110..86eb3919f00 100644 --- a/tests/test_config_entries.py +++ b/tests/test_config_entries.py @@ -314,12 +314,10 @@ async def test_remove_entry_handles_callback_error(hass, manager): assert [item.entry_id for item in manager.async_entries()] == [] -@asyncio.coroutine -def test_remove_entry_raises(hass, manager): +async def test_remove_entry_raises(hass, manager): """Test if a component raises while removing entry.""" - @asyncio.coroutine - def mock_unload_entry(hass, entry): + async def mock_unload_entry(hass, entry): """Mock unload entry function.""" raise Exception("BROKEN") @@ -337,14 +335,13 @@ def test_remove_entry_raises(hass, manager): "test3", ] - result = yield from manager.async_remove("test2") + result = await manager.async_remove("test2") assert result == {"require_restart": True} assert [item.entry_id for item in manager.async_entries()] == ["test1", "test3"] -@asyncio.coroutine -def test_remove_entry_if_not_loaded(hass, manager): +async def test_remove_entry_if_not_loaded(hass, manager): """Test that we can remove an entry that is not loaded.""" mock_unload_entry = MagicMock(return_value=mock_coro(True)) @@ -360,7 +357,7 @@ def test_remove_entry_if_not_loaded(hass, manager): "test3", ] - result = yield from manager.async_remove("test2") + result = await manager.async_remove("test2") assert result == {"require_restart": False} assert [item.entry_id for item in manager.async_entries()] == ["test1", "test3"] @@ -368,8 +365,7 @@ def test_remove_entry_if_not_loaded(hass, manager): assert len(mock_unload_entry.mock_calls) == 0 -@asyncio.coroutine -def test_add_entry_calls_setup_entry(hass, manager): +async def test_add_entry_calls_setup_entry(hass, manager): """Test we call setup_config_entry.""" mock_setup_entry = MagicMock(return_value=mock_coro(True)) @@ -377,18 +373,19 @@ def test_add_entry_calls_setup_entry(hass, manager): mock_entity_platform(hass, "config_flow.comp", None) class TestFlow(config_entries.ConfigFlow): + """Test flow.""" VERSION = 1 - @asyncio.coroutine - def async_step_user(self, user_input=None): + async def async_step_user(self, user_input=None): + """Test user step.""" return self.async_create_entry(title="title", data={"token": "supersecret"}) with patch.dict(config_entries.HANDLERS, {"comp": TestFlow, "beer": 5}): - yield from manager.flow.async_init( + await manager.flow.async_init( "comp", context={"source": config_entries.SOURCE_USER} ) - yield from hass.async_block_till_done() + await hass.async_block_till_done() assert len(mock_setup_entry.mock_calls) == 1 p_hass, p_entry = mock_setup_entry.mock_calls[0][1] @@ -397,8 +394,7 @@ def test_add_entry_calls_setup_entry(hass, manager): assert p_entry.data == {"token": "supersecret"} -@asyncio.coroutine -def test_entries_gets_entries(manager): +async def test_entries_gets_entries(manager): """Test entries are filtered by domain.""" MockConfigEntry(domain="test").add_to_manager(manager) entry1 = MockConfigEntry(domain="test2") @@ -409,8 +405,7 @@ def test_entries_gets_entries(manager): assert manager.async_entries("test2") == [entry1, entry2] -@asyncio.coroutine -def test_domains_gets_uniques(manager): +async def test_domains_gets_uniques(manager): """Test we only return each domain once.""" MockConfigEntry(domain="test").add_to_manager(manager) MockConfigEntry(domain="test2").add_to_manager(manager) @@ -429,10 +424,13 @@ async def test_saving_and_loading(hass): mock_entity_platform(hass, "config_flow.test", None) class TestFlow(config_entries.ConfigFlow): + """Test flow.""" + VERSION = 5 CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_POLL async def async_step_user(self, user_input=None): + """Test user step.""" await self.async_set_unique_id("unique") return self.async_create_entry(title="Test Title", data={"token": "abcd"}) @@ -442,11 +440,13 @@ async def test_saving_and_loading(hass): ) class Test2Flow(config_entries.ConfigFlow): + """Test flow.""" + VERSION = 3 CONNECTION_CLASS = config_entries.CONN_CLASS_CLOUD_PUSH - @asyncio.coroutine - def async_step_user(self, user_input=None): + async def async_step_user(self, user_input=None): + """Test user step.""" return self.async_create_entry( title="Test 2 Title", data={"username": "bla"} ) @@ -528,9 +528,12 @@ async def test_discovery_notification(hass): with patch.dict(config_entries.HANDLERS): class TestFlow(config_entries.ConfigFlow, domain="test"): + """Test flow.""" + VERSION = 5 async def async_step_discovery(self, user_input=None): + """Test discovery step.""" if user_input is not None: return self.async_create_entry( title="Test Title", data={"token": "abcd"} @@ -560,9 +563,12 @@ async def test_discovery_notification_not_created(hass): await async_setup_component(hass, "persistent_notification", {}) class TestFlow(config_entries.ConfigFlow): + """Test flow.""" + VERSION = 5 async def async_step_discovery(self, user_input=None): + """Test discovery step.""" return self.async_abort(reason="test") with patch.dict(config_entries.HANDLERS, {"test": TestFlow}): @@ -685,11 +691,15 @@ async def test_entry_options(hass, manager): entry.add_to_manager(manager) class TestFlow: + """Test flow.""" + @staticmethod @callback def async_get_options_flow(config_entry): + """Test options flow.""" + class OptionsFlowHandler(data_entry_flow.FlowHandler): - pass + """Test options flow handler.""" return OptionsFlowHandler() @@ -703,7 +713,6 @@ async def test_entry_options(hass, manager): await manager.options.async_finish_flow(flow, {"data": {"second": True}}) assert entry.data == {"first": True} - assert entry.options == {"second": True} @@ -1014,10 +1023,12 @@ async def test_unqiue_id_persisted(hass, manager): mock_entity_platform(hass, "config_flow.comp", None) class TestFlow(config_entries.ConfigFlow): + """Test flow.""" VERSION = 1 async def async_step_user(self, user_input=None): + """Test user step.""" await self.async_set_unique_id("mock-unique-id") return self.async_create_entry(title="mock-title", data={}) @@ -1058,10 +1069,12 @@ async def test_unique_id_existing_entry(hass, manager): mock_entity_platform(hass, "config_flow.comp", None) class TestFlow(config_entries.ConfigFlow): + """Test flow.""" VERSION = 1 async def async_step_user(self, user_input=None): + """Test user step.""" existing_entry = await self.async_set_unique_id("mock-unique-id") assert existing_entry is not None @@ -1100,10 +1113,12 @@ async def test_unique_id_update_existing_entry(hass, manager): mock_entity_platform(hass, "config_flow.comp", None) class TestFlow(config_entries.ConfigFlow): + """Test flow.""" VERSION = 1 async def async_step_user(self, user_input=None): + """Test user step.""" await self.async_set_unique_id("mock-unique-id") await self._abort_if_unique_id_configured(updates={"host": "1.1.1.1"}) @@ -1134,10 +1149,12 @@ async def test_unique_id_not_update_existing_entry(hass, manager): mock_entity_platform(hass, "config_flow.comp", None) class TestFlow(config_entries.ConfigFlow): + """Test flow.""" VERSION = 1 async def async_step_user(self, user_input=None): + """Test user step.""" await self.async_set_unique_id("mock-unique-id") await self._abort_if_unique_id_configured(updates={"host": "0.0.0.0"}) @@ -1161,10 +1178,12 @@ async def test_unique_id_in_progress(hass, manager): mock_entity_platform(hass, "config_flow.comp", None) class TestFlow(config_entries.ConfigFlow): + """Test flow.""" VERSION = 1 async def async_step_user(self, user_input=None): + """Test user step.""" await self.async_set_unique_id("mock-unique-id") return self.async_show_form(step_id="discovery") @@ -1193,10 +1212,12 @@ async def test_finish_flow_aborts_progress(hass, manager): mock_entity_platform(hass, "config_flow.comp", None) class TestFlow(config_entries.ConfigFlow): + """Test flow.""" VERSION = 1 async def async_step_user(self, user_input=None): + """Test user step.""" await self.async_set_unique_id("mock-unique-id", raise_on_progress=False) if user_input is None: @@ -1228,10 +1249,12 @@ async def test_unique_id_ignore(hass, manager): mock_entity_platform(hass, "config_flow.comp", None) class TestFlow(config_entries.ConfigFlow): + """Test flow.""" VERSION = 1 async def async_step_user(self, user_input=None): + """Test user flow.""" await self.async_set_unique_id("mock-unique-id") return self.async_show_form(step_id="discovery") @@ -1268,10 +1291,12 @@ async def test_unignore_step_form(hass, manager): mock_entity_platform(hass, "config_flow.comp", None) class TestFlow(config_entries.ConfigFlow): + """Test flow.""" VERSION = 1 async def async_step_unignore(self, user_input): + """Test unignore step.""" unique_id = user_input["unique_id"] await self.async_set_unique_id(unique_id) return self.async_show_form(step_id="discovery") @@ -1310,10 +1335,12 @@ async def test_unignore_create_entry(hass, manager): mock_entity_platform(hass, "config_flow.comp", None) class TestFlow(config_entries.ConfigFlow): + """Test flow.""" VERSION = 1 async def async_step_unignore(self, user_input): + """Test unignore step.""" unique_id = user_input["unique_id"] await self.async_set_unique_id(unique_id) return self.async_create_entry(title="yo", data={}) @@ -1355,6 +1382,7 @@ async def test_unignore_default_impl(hass, manager): mock_entity_platform(hass, "config_flow.comp", None) class TestFlow(config_entries.ConfigFlow): + """Test flow.""" VERSION = 1 @@ -1395,10 +1423,12 @@ async def test_partial_flows_hidden(hass, manager): pause_discovery = asyncio.Event() class TestFlow(config_entries.ConfigFlow): + """Test flow.""" VERSION = 1 async def async_step_discovery(self, user_input): + """Test discovery step.""" discovery_started.set() await pause_discovery.wait() return self.async_show_form(step_id="someform") diff --git a/tests/test_setup.py b/tests/test_setup.py index f90a7269752..daa9c6e8406 100644 --- a/tests/test_setup.py +++ b/tests/test_setup.py @@ -1,6 +1,5 @@ """Test component/platform setup.""" # pylint: disable=protected-access -import asyncio import logging import os import threading @@ -265,8 +264,7 @@ class TestSetup: """Test component setup while waiting for lock is not set up twice.""" result = [] - @asyncio.coroutine - def async_setup(hass, config): + async def async_setup(hass, config): """Tracking Setup.""" result.append(1) @@ -462,21 +460,17 @@ class TestSetup: assert call_order == [1, 1, 2] -@asyncio.coroutine -def test_component_cannot_depend_config(hass): +async def test_component_cannot_depend_config(hass): """Test config is not allowed to be a dependency.""" - result = yield from setup._async_process_dependencies( - hass, None, "test", ["config"] - ) + result = await setup._async_process_dependencies(hass, None, "test", ["config"]) assert not result -@asyncio.coroutine -def test_component_warn_slow_setup(hass): +async def test_component_warn_slow_setup(hass): """Warn we log when a component setup takes a long time.""" mock_integration(hass, MockModule("test_component1")) with mock.patch.object(hass.loop, "call_later", mock.MagicMock()) as mock_call: - result = yield from setup.async_setup_component(hass, "test_component1", {}) + result = await setup.async_setup_component(hass, "test_component1", {}) assert result assert mock_call.called assert len(mock_call.mock_calls) == 3 @@ -489,14 +483,13 @@ def test_component_warn_slow_setup(hass): assert mock_call().cancel.called -@asyncio.coroutine -def test_platform_no_warn_slow(hass): +async def test_platform_no_warn_slow(hass): """Do not warn for long entity setup time.""" mock_integration( hass, MockModule("test_component1", platform_schema=PLATFORM_SCHEMA) ) with mock.patch.object(hass.loop, "call_later", mock.MagicMock()) as mock_call: - result = yield from setup.async_setup_component(hass, "test_component1", {}) + result = await setup.async_setup_component(hass, "test_component1", {}) assert result assert not mock_call.called diff --git a/tests/test_util/aiohttp.py b/tests/test_util/aiohttp.py index e0e1ded32c3..e23ba5cb9f5 100644 --- a/tests/test_util/aiohttp.py +++ b/tests/test_util/aiohttp.py @@ -1,5 +1,4 @@ """Aiohttp test utils.""" -import asyncio from contextlib import contextmanager import json as _json import re @@ -13,7 +12,7 @@ from yarl import URL from homeassistant.const import EVENT_HOMEASSISTANT_CLOSE -retype = type(re.compile("")) +RETYPE = type(re.compile("")) def mock_stream(data): @@ -58,7 +57,7 @@ class AiohttpClientMocker: if content is None: content = b"" - if not isinstance(url, retype): + if not isinstance(url, RETYPE): url = URL(url) if params: url = url.with_query(params) @@ -173,7 +172,7 @@ class AiohttpClientMockResponse: return False # regular expression matching - if isinstance(self._url, retype): + if isinstance(self._url, RETYPE): return self._url.search(str(url)) is not None if ( @@ -220,25 +219,20 @@ class AiohttpClientMockResponse: """Return content.""" return mock_stream(self.response) - @asyncio.coroutine - def read(self): + async def read(self): """Return mock response.""" return self.response - @asyncio.coroutine - def text(self, encoding="utf-8"): + async def text(self, encoding="utf-8"): """Return mock response as a string.""" return self.response.decode(encoding) - @asyncio.coroutine - def json(self, encoding="utf-8"): + async def json(self, encoding="utf-8"): """Return mock response as a json.""" return _json.loads(self.response.decode(encoding)) - @asyncio.coroutine def release(self): """Mock release.""" - pass def raise_for_status(self): """Raise error if status is 400 or higher.""" @@ -253,7 +247,6 @@ class AiohttpClientMockResponse: def close(self): """Mock close.""" - pass @contextmanager diff --git a/tests/util/test_logging.py b/tests/util/test_logging.py index d5f8eb4a2c7..c2c9d4803f9 100644 --- a/tests/util/test_logging.py +++ b/tests/util/test_logging.py @@ -19,8 +19,7 @@ def test_sensitive_data_filter(): assert sensitive_record.msg == "******* log" -@asyncio.coroutine -def test_async_handler_loop_log(loop): +async def test_async_handler_loop_log(loop): """Test logging data inside from inside the event loop.""" loop._thread_ident = threading.get_ident() @@ -39,13 +38,12 @@ def test_async_handler_loop_log(loop): log_record = logging.makeLogRecord({"msg": "Test Log Record"}) handler.emit(log_record) - yield from handler.async_close(True) + await handler.async_close(True) assert queue.get_nowait().msg == "Test Log Record" assert queue.empty() -@asyncio.coroutine -def test_async_handler_thread_log(loop): +async def test_async_handler_thread_log(loop): """Test logging data from a thread.""" loop._thread_ident = threading.get_ident() @@ -60,8 +58,8 @@ def test_async_handler_thread_log(loop): handler.emit(log_record) handler.close() - yield from loop.run_in_executor(None, add_log) - yield from handler.async_close(True) + await loop.run_in_executor(None, add_log) + await handler.async_close(True) assert queue.get_nowait().msg == "Test Log Record" assert queue.empty()