Skip to content

Commit

Permalink
Upgrade pytest-aiohttp (#82475)
Browse files Browse the repository at this point in the history
* Upgrade pytest-aiohttp

* Make sure executors, tasks and timers are closed

Some test will trigger warnings on garbage collect, these warnings
spills over into next test.

Some test trigger tasks that raise errors on shutdown, these spill
over into next test.

This is to mimic older pytest-aiohttp and it's behaviour on test
cleanup.

Discussions on similar changes for pytest-aiohttp are here:
pytest-dev/pytest-asyncio#309

* Replace loop with event_loop

* Make sure time is frozen for tests

* Make sure the ConditionType is not async

  /home-assistant/homeassistant/helpers/template.py:2082: RuntimeWarning: coroutine 'AsyncMockMixin._execute_mock_call' was never awaited
    def wrapper(*args, **kwargs):
  Enable tracemalloc to get traceback where the object was allocated.
  See https://docs.pytest.org/en/stable/how-to/capture-warnings.html#resource-warnings for more info.

* Increase litejet press tests with a factor 10

The times are simulated anyway, and we can't stop the normal
event from occuring.

* Use async handlers for aiohttp

tests/components/motioneye/test_camera.py::test_get_still_image_from_camera
tests/components/motioneye/test_camera.py::test_get_still_image_from_camera
tests/components/motioneye/test_camera.py::test_get_stream_from_camera
tests/components/motioneye/test_camera.py::test_get_stream_from_camera
tests/components/motioneye/test_camera.py::test_camera_option_stream_url_template
tests/components/motioneye/test_camera.py::test_camera_option_stream_url_template
  /Users/joakim/src/hass/home-assistant/venv/lib/python3.9/site-packages/aiohttp/web_urldispatcher.py:189: DeprecationWarning: Bare functions are deprecated, use async ones
    warnings.warn(

* Switch to freezegun in modbus tests

The tests allowed clock to tick in between steps

* Make sure skybell object are fully mocked

Old tests would trigger attempts to post to could services:

```
DEBUG:aioskybell:HTTP post https://cloud.myskybell.com/api/v3/login/ Request with headers: {'content-type': 'application/json', 'accept': '*/*', 'x-skybell-app-id': 'd2b542c7-a7e4-4e1e-b77d-2b76911c7c46', 'x-skybell-client-id': '1f36a3c0-6dee-4997-a6db-4e1c67338e57'}
```

* Fix sorting that broke after rebase
  • Loading branch information
elupus committed Nov 29, 2022
1 parent b7652c7 commit c576a68
Show file tree
Hide file tree
Showing 42 changed files with 263 additions and 226 deletions.
3 changes: 0 additions & 3 deletions homeassistant/package_constraints.txt
Expand Up @@ -98,9 +98,6 @@ hyperframe>=5.2.0
# Ensure we run compatible with musllinux build env
numpy==1.23.2

# pytest_asyncio breaks our test suite. We rely on pytest-aiohttp instead
pytest_asyncio==1000000000.0.0

# Prevent dependency conflicts between sisyphus-control and aioambient
# until upper bounds for sisyphus-control have been updated
# https://github.com/jkeljo/sisyphus-control/issues/6
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Expand Up @@ -227,3 +227,4 @@ norecursedirs = [
]
log_format = "%(asctime)s.%(msecs)03d %(levelname)-8s %(threadName)s %(name)s:%(filename)s:%(lineno)s %(message)s"
log_date_format = "%Y-%m-%d %H:%M:%S"
asyncio_mode = "auto"
3 changes: 2 additions & 1 deletion requirements_test.txt
Expand Up @@ -16,7 +16,8 @@ mypy==0.991
pre-commit==2.20.0
pylint==2.15.6
pipdeptree==2.3.1
pytest-aiohttp==0.3.0
pytest-asyncio==0.20.2
pytest-aiohttp==1.0.4
pytest-cov==3.0.0
pytest-freezegun==0.4.2
pytest-socket==0.5.1
Expand Down
3 changes: 0 additions & 3 deletions script/gen_requirements_all.py
Expand Up @@ -110,9 +110,6 @@
# Ensure we run compatible with musllinux build env
numpy==1.23.2
# pytest_asyncio breaks our test suite. We rely on pytest-aiohttp instead
pytest_asyncio==1000000000.0.0
# Prevent dependency conflicts between sisyphus-control and aioambient
# until upper bounds for sisyphus-control have been updated
# https://github.com/jkeljo/sisyphus-control/issues/6
Expand Down
2 changes: 1 addition & 1 deletion tests/auth/test_init.py
Expand Up @@ -28,7 +28,7 @@


@pytest.fixture
def mock_hass(loop):
def mock_hass(event_loop):
"""Home Assistant mock with minimum amount of data set to make it work with auth."""
hass = Mock()
hass.config.skip_pip = True
Expand Down
2 changes: 1 addition & 1 deletion tests/common.py
Expand Up @@ -160,7 +160,7 @@ def stop_hass():


# pylint: disable=protected-access
async def async_test_home_assistant(loop, load_registries=True):
async def async_test_home_assistant(event_loop, load_registries=True):
"""Return a Home Assistant object pointing at test config dir."""
hass = ha.HomeAssistant()
store = auth_store.AuthStore(hass)
Expand Down
3 changes: 2 additions & 1 deletion tests/components/alexa/test_flash_briefings.py
Expand Up @@ -21,8 +21,9 @@


@pytest.fixture
def alexa_client(loop, hass, hass_client):
def alexa_client(event_loop, hass, hass_client):
"""Initialize a Home Assistant server for testing this module."""
loop = event_loop

@callback
def mock_service(call):
Expand Down
3 changes: 2 additions & 1 deletion tests/components/alexa/test_intent.py
Expand Up @@ -27,8 +27,9 @@


@pytest.fixture
def alexa_client(loop, hass, hass_client):
def alexa_client(event_loop, hass, hass_client):
"""Initialize a Home Assistant server for testing this module."""
loop = event_loop

@callback
def mock_service(call):
Expand Down
2 changes: 1 addition & 1 deletion tests/components/auth/conftest.py
Expand Up @@ -3,6 +3,6 @@


@pytest.fixture
def aiohttp_client(loop, aiohttp_client, socket_enabled):
def aiohttp_client(event_loop, aiohttp_client, socket_enabled):
"""Return aiohttp_client and allow opening sockets."""
return aiohttp_client
2 changes: 1 addition & 1 deletion tests/components/config/test_init.py
Expand Up @@ -2,7 +2,7 @@
from homeassistant.setup import async_setup_component


async def test_config_setup(hass, loop):
async def test_config_setup(hass, event_loop):
"""Test it sets up hassbian."""
await async_setup_component(hass, "config", {})
assert "config" in hass.config.components
2 changes: 1 addition & 1 deletion tests/components/emulated_hue/test_upnp.py
Expand Up @@ -31,7 +31,7 @@ def sendto(self, response, addr):


@pytest.fixture
def aiohttp_client(loop, aiohttp_client, socket_enabled):
def aiohttp_client(event_loop, aiohttp_client, socket_enabled):
"""Return aiohttp_client and allow opening sockets."""
return aiohttp_client

Expand Down
2 changes: 1 addition & 1 deletion tests/components/emulated_roku/test_binding.py
Expand Up @@ -25,7 +25,7 @@ async def test_events_fired_properly(hass):
roku_event_handler = None

def instantiate(
loop,
event_loop,
handler,
roku_usn,
host_ip,
Expand Down
8 changes: 8 additions & 0 deletions tests/components/energy/test_sensor.py
Expand Up @@ -3,6 +3,7 @@
from datetime import timedelta
from unittest.mock import patch

from freezegun import freeze_time
import pytest

from homeassistant.components.energy import data
Expand Down Expand Up @@ -41,6 +42,13 @@ async def setup_integration(hass):
return setup_integration


@pytest.fixture(autouse=True)
@freeze_time("2022-04-19 07:53:05")
def frozen_time():
"""Freeze clock for tests."""
yield


def get_statistics_for_entity(statistics_results, entity_id):
"""Get statistics for a certain entity, or None if there is none."""
for statistics_result in statistics_results:
Expand Down
2 changes: 1 addition & 1 deletion tests/components/fido/test_sensor.py
Expand Up @@ -38,7 +38,7 @@ async def fetch_data(self):
raise PyFidoError("Fake Error")


async def test_fido_sensor(loop, hass):
async def test_fido_sensor(event_loop, hass):
"""Test the Fido number sensor."""
with patch("homeassistant.components.fido.sensor.FidoClient", new=FidoClientMock):
config = {
Expand Down
2 changes: 1 addition & 1 deletion tests/components/frontend/test_init.py
Expand Up @@ -80,7 +80,7 @@ async def frontend_themes(hass):


@pytest.fixture
def aiohttp_client(loop, aiohttp_client, socket_enabled):
def aiohttp_client(event_loop, aiohttp_client, socket_enabled):
"""Return aiohttp_client and allow opening sockets."""
return aiohttp_client

Expand Down
4 changes: 2 additions & 2 deletions tests/components/geofency/test_init.py
Expand Up @@ -117,7 +117,7 @@ def mock_dev_track(mock_device_tracker_conf):


@pytest.fixture
async def geofency_client(loop, hass, hass_client_no_auth):
async def geofency_client(event_loop, hass, hass_client_no_auth):
"""Geofency mock client (unauthenticated)."""

assert await async_setup_component(
Expand All @@ -130,7 +130,7 @@ async def geofency_client(loop, hass, hass_client_no_auth):


@pytest.fixture(autouse=True)
async def setup_zones(loop, hass):
async def setup_zones(event_loop, hass):
"""Set up Zone config in HA."""
assert await async_setup_component(
hass,
Expand Down
7 changes: 5 additions & 2 deletions tests/components/google_assistant/test_google_assistant.py
Expand Up @@ -42,8 +42,9 @@ def auth_header(hass_access_token):


@pytest.fixture
def assistant_client(loop, hass, hass_client_no_auth):
def assistant_client(event_loop, hass, hass_client_no_auth):
"""Create web client for the Google Assistant API."""
loop = event_loop
loop.run_until_complete(
setup.async_setup_component(
hass,
Expand All @@ -66,8 +67,10 @@ def assistant_client(loop, hass, hass_client_no_auth):


@pytest.fixture
def hass_fixture(loop, hass):
def hass_fixture(event_loop, hass):
"""Set up a Home Assistant instance for these tests."""
loop = event_loop

# We need to do this to get access to homeassistant/turn_(on,off)
loop.run_until_complete(setup.async_setup_component(hass, core.DOMAIN, {}))

Expand Down
4 changes: 2 additions & 2 deletions tests/components/gpslogger/test_init.py
Expand Up @@ -26,7 +26,7 @@ def mock_dev_track(mock_device_tracker_conf):


@pytest.fixture
async def gpslogger_client(loop, hass, hass_client_no_auth):
async def gpslogger_client(event_loop, hass, hass_client_no_auth):
"""Mock client for GPSLogger (unauthenticated)."""

assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
Expand All @@ -38,7 +38,7 @@ async def gpslogger_client(loop, hass, hass_client_no_auth):


@pytest.fixture(autouse=True)
async def setup_zones(loop, hass):
async def setup_zones(event_loop, hass):
"""Set up Zone config in HA."""
assert await async_setup_component(
hass,
Expand Down
12 changes: 6 additions & 6 deletions tests/components/homekit/conftest.py
Expand Up @@ -21,7 +21,7 @@ def iid_storage(hass):


@pytest.fixture()
def run_driver(hass, loop, iid_storage):
def run_driver(hass, event_loop, iid_storage):
"""Return a custom AccessoryDriver instance for HomeKit accessory init.
This mock does not mock async_stop, so the driver will not be stopped
Expand All @@ -41,12 +41,12 @@ def run_driver(hass, loop, iid_storage):
bridge_name=BRIDGE_NAME,
iid_storage=iid_storage,
address="127.0.0.1",
loop=loop,
loop=event_loop,
)


@pytest.fixture
def hk_driver(hass, loop, iid_storage):
def hk_driver(hass, event_loop, iid_storage):
"""Return a custom AccessoryDriver instance for HomeKit accessory init."""
with patch("pyhap.accessory_driver.AsyncZeroconf"), patch(
"pyhap.accessory_driver.AccessoryEncoder"
Expand All @@ -65,12 +65,12 @@ def hk_driver(hass, loop, iid_storage):
bridge_name=BRIDGE_NAME,
iid_storage=iid_storage,
address="127.0.0.1",
loop=loop,
loop=event_loop,
)


@pytest.fixture
def mock_hap(hass, loop, iid_storage, mock_zeroconf):
def mock_hap(hass, event_loop, iid_storage, mock_zeroconf):
"""Return a custom AccessoryDriver instance for HomeKit accessory init."""
with patch("pyhap.accessory_driver.AsyncZeroconf"), patch(
"pyhap.accessory_driver.AccessoryEncoder"
Expand All @@ -93,7 +93,7 @@ def mock_hap(hass, loop, iid_storage, mock_zeroconf):
bridge_name=BRIDGE_NAME,
iid_storage=iid_storage,
address="127.0.0.1",
loop=loop,
loop=event_loop,
)


Expand Down
2 changes: 1 addition & 1 deletion tests/components/http/conftest.py
Expand Up @@ -3,6 +3,6 @@


@pytest.fixture
def aiohttp_client(loop, aiohttp_client, socket_enabled):
def aiohttp_client(event_loop, aiohttp_client, socket_enabled):
"""Return aiohttp_client and allow opening sockets."""
return aiohttp_client
4 changes: 2 additions & 2 deletions tests/components/http/test_cors.py
Expand Up @@ -49,12 +49,12 @@ async def mock_handler(request):


@pytest.fixture
def client(loop, aiohttp_client):
def client(event_loop, aiohttp_client):
"""Fixture to set up a web.Application."""
app = web.Application()
setup_cors(app, [TRUSTED_ORIGIN])
app["allow_configured_cors"](app.router.add_get("/", mock_handler))
return loop.run_until_complete(aiohttp_client(app))
return event_loop.run_until_complete(aiohttp_client(app))


async def test_cors_requests(client):
Expand Down
2 changes: 1 addition & 1 deletion tests/components/image_processing/test_init.py
Expand Up @@ -15,7 +15,7 @@


@pytest.fixture
def aiohttp_unused_port(loop, aiohttp_unused_port, socket_enabled):
def aiohttp_unused_port(event_loop, aiohttp_unused_port, socket_enabled):
"""Return aiohttp_unused_port and allow opening sockets."""
return aiohttp_unused_port

Expand Down

0 comments on commit c576a68

Please sign in to comment.