core/tests/conftest.py

200 lines
5.4 KiB
Python
Raw Normal View History

2018-08-19 20:29:08 +00:00
"""Set up some common test helper things."""
2017-03-07 09:11:41 +00:00
import asyncio
import functools
import logging
2017-03-07 09:11:41 +00:00
import os
2019-02-07 21:50:59 +00:00
from unittest.mock import patch
import pytest
import requests_mock as _requests_mock
Fix MQTT retained message not being re-dispatched (#12004) * Fix MQTT retained message not being re-dispatched * Fix tests * Use paho-mqtt for retained messages * Improve code style * Store list of subscribers * Fix lint error * Adhere to Home Assistant's logging standard "Try to avoid brackets and additional quotes around the output to make it easier for users to parse the log." - https://home-assistant.io/developers/development_guidelines/ * Add reconnect tests * Fix lint error * Introduce Subscription Tests still need to be updated * Use namedtuple for MQTT messages ... And fix issues Accessing the config manually at runtime isn't ideal * Fix MQTT __init__.py tests * Updated usage of Mocks * Moved tests that were testing subscriptions out of the MQTTComponent test, because of how mock.patch was used * Adjusted the remaining tests for the MQTT clients new behavior - e.g. self.progress was removed * Updated the async_fire_mqtt_message helper * ✅ Update MQTT tests * Re-introduce the MQTT subscriptions through the dispatcher for tests - quite ugly though... 🚧 * Update fixtures to use our new MQTT mock 🎨 * 📝 Update base code according to comments * 🔨 Adjust MQTT test base * 🔨 Update other MQTT tests * 🍎 Fix carriage return in source files Apparently test_mqtt_json.py and test_mqtt_template.py were written on Windows. In order to not mess up the diff, I'll just redo the carriage return. * 🎨 Remove unused import * 📝 Remove fire_mqtt_client_message * 🐛 Fix using python 3.6 method What's very interesting is that 3.4 didn't fail on travis... * 🐛 Fix using assert directly
2018-02-11 17:17:58 +00:00
from homeassistant import util
from homeassistant.util import location
from homeassistant.auth.const import GROUP_ID_ADMIN, GROUP_ID_READ_ONLY
from homeassistant.auth.providers import legacy_api_password, homeassistant
pytest.register_assert_rewrite("tests.common")
from tests.common import ( # noqa: E402 module level import not at top of file
2019-07-31 19:25:30 +00:00
async_test_home_assistant,
INSTANCES,
mock_coro,
mock_storage as mock_storage,
MockUser,
CLIENT_ID,
)
from tests.test_util.aiohttp import (
mock_aiohttp_client,
) # noqa: E402 module level import not at top of file
2019-07-31 19:25:30 +00:00
if os.environ.get("UVLOOP") == "1":
2017-03-07 09:11:41 +00:00
import uvloop
2019-07-31 19:25:30 +00:00
2017-03-07 09:11:41 +00:00
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
logging.basicConfig(level=logging.DEBUG)
2019-07-31 19:25:30 +00:00
logging.getLogger("sqlalchemy.engine").setLevel(logging.INFO)
def check_real(func):
"""Force a function to require a keyword _test_real to be passed in."""
2019-07-31 19:25:30 +00:00
@functools.wraps(func)
def guard_func(*args, **kwargs):
2019-07-31 19:25:30 +00:00
real = kwargs.pop("_test_real", None)
if not real:
2019-07-31 19:25:30 +00:00
raise Exception(
'Forgot to mock or pass "_test_real=True" to %s', func.__name__
)
return func(*args, **kwargs)
return guard_func
2016-11-19 05:47:59 +00:00
# Guard a few functions that would make network connections
2019-07-31 19:25:30 +00:00
location.async_detect_location_info = check_real(location.async_detect_location_info)
util.get_local_ip = lambda: "127.0.0.1"
@pytest.fixture(autouse=True)
def verify_cleanup():
"""Verify that the test has cleaned up resources correctly."""
yield
if len(INSTANCES) >= 2:
count = len(INSTANCES)
for inst in INSTANCES:
inst.stop()
2019-07-31 19:25:30 +00:00
pytest.exit(
"Detected non stopped instances " "({}), aborting test run".format(count)
)
@pytest.fixture
def hass_storage():
"""Fixture to mock storage."""
with mock_storage() as stored_data:
yield stored_data
@pytest.fixture
def hass(loop, hass_storage):
"""Fixture to provide a test instance of HASS."""
hass = loop.run_until_complete(async_test_home_assistant(loop))
yield hass
loop.run_until_complete(hass.async_stop(force=True))
@pytest.fixture
def requests_mock():
"""Fixture to provide a requests mocker."""
with _requests_mock.mock() as m:
yield m
@pytest.fixture
def aioclient_mock():
"""Fixture to mock aioclient calls."""
with mock_aiohttp_client() as mock_session:
yield mock_session
@pytest.fixture
def mock_device_tracker_conf():
"""Prevent device tracker from reading/writing data."""
devices = []
async def mock_update_config(path, id, entity):
devices.append(entity)
with patch(
2019-07-31 19:25:30 +00:00
"homeassistant.components.device_tracker.legacy"
".DeviceTracker.async_update_config",
side_effect=mock_update_config,
), patch(
2019-07-31 19:25:30 +00:00
"homeassistant.components.device_tracker.legacy.async_load_config",
side_effect=lambda *args: mock_coro(devices),
):
yield devices
@pytest.fixture
def hass_access_token(hass, hass_admin_user):
"""Return an access token to access Home Assistant."""
refresh_token = hass.loop.run_until_complete(
2019-07-31 19:25:30 +00:00
hass.auth.async_create_refresh_token(hass_admin_user, CLIENT_ID)
)
return hass.auth.async_create_access_token(refresh_token)
@pytest.fixture
def hass_owner_user(hass, local_auth):
"""Return a Home Assistant admin user."""
return MockUser(is_owner=True).add_to_hass(hass)
@pytest.fixture
def hass_admin_user(hass, local_auth):
"""Return a Home Assistant admin user."""
2019-07-31 19:25:30 +00:00
admin_group = hass.loop.run_until_complete(
hass.auth.async_get_group(GROUP_ID_ADMIN)
)
return MockUser(groups=[admin_group]).add_to_hass(hass)
@pytest.fixture
def hass_read_only_user(hass, local_auth):
"""Return a Home Assistant read only user."""
2019-07-31 19:25:30 +00:00
read_only_group = hass.loop.run_until_complete(
hass.auth.async_get_group(GROUP_ID_READ_ONLY)
)
return MockUser(groups=[read_only_group]).add_to_hass(hass)
@pytest.fixture
def hass_read_only_access_token(hass, hass_read_only_user):
"""Return a Home Assistant read only user."""
refresh_token = hass.loop.run_until_complete(
2019-07-31 19:25:30 +00:00
hass.auth.async_create_refresh_token(hass_read_only_user, CLIENT_ID)
)
return hass.auth.async_create_access_token(refresh_token)
@pytest.fixture
def legacy_auth(hass):
"""Load legacy API password provider."""
prv = legacy_api_password.LegacyApiPasswordAuthProvider(
2019-07-31 19:25:30 +00:00
hass,
hass.auth._store,
{"type": "legacy_api_password", "api_password": "test-password"},
)
hass.auth._providers[(prv.type, prv.id)] = prv
return prv
@pytest.fixture
def local_auth(hass):
"""Load local auth provider."""
prv = homeassistant.HassAuthProvider(
2019-07-31 19:25:30 +00:00
hass, hass.auth._store, {"type": "homeassistant"}
)
hass.auth._providers[(prv.type, prv.id)] = prv
return prv
@pytest.fixture
def hass_client(hass, aiohttp_client, hass_access_token):
"""Return an authenticated HTTP client."""
2019-07-31 19:25:30 +00:00
async def auth_client():
"""Return an authenticated client."""
2019-07-31 19:25:30 +00:00
return await aiohttp_client(
hass.http.app,
headers={"Authorization": "Bearer {}".format(hass_access_token)},
)
return auth_client