Update sensor recorder tests to async (#124061)

This commit is contained in:
Erik Montnemery 2024-08-18 20:20:58 +02:00 committed by GitHub
parent 7d5ddbf51c
commit ce2ffde22e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 54 additions and 38 deletions

View File

@ -107,6 +107,7 @@ _TEST_FIXTURES: dict[str, list[str] | str] = {
"device_registry": "DeviceRegistry", "device_registry": "DeviceRegistry",
"enable_bluetooth": "None", "enable_bluetooth": "None",
"enable_custom_integrations": "None", "enable_custom_integrations": "None",
"enable_missing_statistics": "bool",
"enable_nightly_purge": "bool", "enable_nightly_purge": "bool",
"enable_statistics": "bool", "enable_statistics": "bool",
"enable_schema_validation": "bool", "enable_schema_validation": "bool",

View File

@ -251,6 +251,7 @@ async def async_test_home_assistant(
event_loop: asyncio.AbstractEventLoop | None = None, event_loop: asyncio.AbstractEventLoop | None = None,
load_registries: bool = True, load_registries: bool = True,
config_dir: str | None = None, config_dir: str | None = None,
initial_state: CoreState = CoreState.running,
) -> AsyncGenerator[HomeAssistant]: ) -> AsyncGenerator[HomeAssistant]:
"""Return a Home Assistant object pointing at test config dir.""" """Return a Home Assistant object pointing at test config dir."""
hass = HomeAssistant(config_dir or get_test_config_dir()) hass = HomeAssistant(config_dir or get_test_config_dir())
@ -378,7 +379,7 @@ async def async_test_home_assistant(
await rs.async_load(hass) await rs.async_load(hass)
hass.data[bootstrap.DATA_REGISTRIES_LOADED] = None hass.data[bootstrap.DATA_REGISTRIES_LOADED] = None
hass.set_state(CoreState.running) hass.set_state(initial_state)
@callback @callback
def clear_instance(event): def clear_instance(event):

View File

@ -1366,7 +1366,7 @@ async def test_statistics_runs_initiated(
@pytest.mark.freeze_time("2022-09-13 09:00:00+02:00") @pytest.mark.freeze_time("2022-09-13 09:00:00+02:00")
@pytest.mark.parametrize("persistent_database", [True]) @pytest.mark.parametrize("persistent_database", [True])
@pytest.mark.parametrize("enable_statistics", [True]) @pytest.mark.parametrize("enable_missing_statistics", [True])
@pytest.mark.usefixtures("hass_storage") # Prevent test hass from writing to storage @pytest.mark.usefixtures("hass_storage") # Prevent test hass from writing to storage
async def test_compile_missing_statistics( async def test_compile_missing_statistics(
async_test_recorder: RecorderInstanceGenerator, freezer: FrozenDateTimeFactory async_test_recorder: RecorderInstanceGenerator, freezer: FrozenDateTimeFactory

View File

@ -1,7 +1,6 @@
"""The tests for sensor recorder platform can catch up.""" """The tests for sensor recorder platform can catch up."""
from datetime import datetime, timedelta from datetime import datetime, timedelta
from pathlib import Path
import threading import threading
from unittest.mock import patch from unittest.mock import patch
@ -17,11 +16,15 @@ from homeassistant.components.recorder.statistics import (
from homeassistant.components.recorder.util import session_scope from homeassistant.components.recorder.util import session_scope
from homeassistant.core import CoreState from homeassistant.core import CoreState
from homeassistant.helpers import recorder as recorder_helper from homeassistant.helpers import recorder as recorder_helper
from homeassistant.setup import setup_component from homeassistant.setup import async_setup_component
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
from tests.common import get_test_home_assistant from tests.common import async_test_home_assistant
from tests.components.recorder.common import do_adhoc_statistics, wait_recording_done from tests.components.recorder.common import (
async_wait_recording_done,
do_adhoc_statistics,
)
from tests.typing import RecorderInstanceGenerator
POWER_SENSOR_ATTRIBUTES = { POWER_SENSOR_ATTRIBUTES = {
"device_class": "energy", "device_class": "energy",
@ -40,37 +43,34 @@ def disable_db_issue_creation():
@pytest.mark.timeout(25) @pytest.mark.timeout(25)
def test_compile_missing_statistics( @pytest.mark.parametrize("persistent_database", [True])
freezer: FrozenDateTimeFactory, recorder_db_url: str, tmp_path: Path @pytest.mark.parametrize("enable_missing_statistics", [True])
@pytest.mark.usefixtures("hass_storage") # Prevent test hass from writing to storage
async def test_compile_missing_statistics(
async_test_recorder: RecorderInstanceGenerator, freezer: FrozenDateTimeFactory
) -> None: ) -> None:
"""Test compile missing statistics.""" """Test compile missing statistics."""
if recorder_db_url == "sqlite://":
# On-disk database because we need to stop and start hass
# and have it persist.
recorder_db_url = "sqlite:///" + str(tmp_path / "pytest.db")
config = {
"db_url": recorder_db_url,
}
three_days_ago = datetime(2021, 1, 1, 0, 0, 0, tzinfo=dt_util.UTC) three_days_ago = datetime(2021, 1, 1, 0, 0, 0, tzinfo=dt_util.UTC)
start_time = three_days_ago + timedelta(days=3) start_time = three_days_ago + timedelta(days=3)
freezer.move_to(three_days_ago) freezer.move_to(three_days_ago)
with get_test_home_assistant() as hass: async with (
hass.set_state(CoreState.not_running) async_test_home_assistant(initial_state=CoreState.not_running) as hass,
async_test_recorder(hass, wait_recorder=False),
):
recorder_helper.async_initialize_recorder(hass) recorder_helper.async_initialize_recorder(hass)
setup_component(hass, "sensor", {}) await async_setup_component(hass, "sensor", {})
setup_component(hass, "recorder", {"recorder": config})
get_instance(hass).recorder_and_worker_thread_ids.add(threading.get_ident()) get_instance(hass).recorder_and_worker_thread_ids.add(threading.get_ident())
hass.start() await hass.async_start()
wait_recording_done(hass) await async_wait_recording_done(hass)
wait_recording_done(hass) await async_wait_recording_done(hass)
hass.states.set("sensor.test1", "0", POWER_SENSOR_ATTRIBUTES) hass.states.async_set("sensor.test1", "0", POWER_SENSOR_ATTRIBUTES)
wait_recording_done(hass) await async_wait_recording_done(hass)
two_days_ago = three_days_ago + timedelta(days=1) two_days_ago = three_days_ago + timedelta(days=1)
freezer.move_to(two_days_ago) freezer.move_to(two_days_ago)
do_adhoc_statistics(hass, start=two_days_ago) do_adhoc_statistics(hass, start=two_days_ago)
wait_recording_done(hass) await async_wait_recording_done(hass)
with session_scope(hass=hass, read_only=True) as session: with session_scope(hass=hass, read_only=True) as session:
latest = get_latest_short_term_statistics_with_session( latest = get_latest_short_term_statistics_with_session(
hass, session, {"sensor.test1"}, {"state", "sum"} hass, session, {"sensor.test1"}, {"state", "sum"}
@ -82,29 +82,32 @@ def test_compile_missing_statistics(
past_time = two_days_ago past_time = two_days_ago
while past_time <= start_time: while past_time <= start_time:
freezer.move_to(past_time) freezer.move_to(past_time)
hass.states.set("sensor.test1", str(count), POWER_SENSOR_ATTRIBUTES) hass.states.async_set("sensor.test1", str(count), POWER_SENSOR_ATTRIBUTES)
past_time += timedelta(minutes=5) past_time += timedelta(minutes=5)
count += 1 count += 1
wait_recording_done(hass) await async_wait_recording_done(hass)
states = get_significant_states( states = get_significant_states(
hass, three_days_ago, past_time, ["sensor.test1"] hass, three_days_ago, past_time, ["sensor.test1"]
) )
assert len(states["sensor.test1"]) == 577 assert len(states["sensor.test1"]) == 577
hass.stop() await hass.async_stop()
await hass.async_block_till_done()
freezer.move_to(start_time) freezer.move_to(start_time)
with get_test_home_assistant() as hass: async with (
hass.set_state(CoreState.not_running) async_test_home_assistant(initial_state=CoreState.not_running) as hass,
async_test_recorder(hass, wait_recorder=False),
):
recorder_helper.async_initialize_recorder(hass) recorder_helper.async_initialize_recorder(hass)
setup_component(hass, "sensor", {}) await async_setup_component(hass, "sensor", {})
hass.states.set("sensor.test1", "0", POWER_SENSOR_ATTRIBUTES) hass.states.async_set("sensor.test1", "0", POWER_SENSOR_ATTRIBUTES)
setup_component(hass, "recorder", {"recorder": config})
get_instance(hass).recorder_and_worker_thread_ids.add(threading.get_ident()) get_instance(hass).recorder_and_worker_thread_ids.add(threading.get_ident())
hass.start() await hass.async_start()
wait_recording_done(hass) await async_wait_recording_done(hass)
wait_recording_done(hass) await async_wait_recording_done(hass)
with session_scope(hass=hass, read_only=True) as session: with session_scope(hass=hass, read_only=True) as session:
latest = get_latest_short_term_statistics_with_session( latest = get_latest_short_term_statistics_with_session(
hass, session, {"sensor.test1"}, {"state", "sum", "max", "mean", "min"} hass, session, {"sensor.test1"}, {"state", "sum", "max", "mean", "min"}
@ -128,4 +131,4 @@ def test_compile_missing_statistics(
assert len(stats["sensor.test1"]) == 48 assert len(stats["sensor.test1"]) == 48
# Make sure the last mean is 570.5 # Make sure the last mean is 570.5
assert stats["sensor.test1"][-1]["mean"] == 570.5 assert stats["sensor.test1"][-1]["mean"] == 570.5
hass.stop() await hass.async_stop()

View File

@ -1262,6 +1262,16 @@ def enable_statistics() -> bool:
return False return False
@pytest.fixture
def enable_missing_statistics() -> bool:
"""Fixture to control enabling of recorder's statistics compilation.
To enable statistics, tests can be marked with:
@pytest.mark.parametrize("enable_missing_statistics", [True])
"""
return False
@pytest.fixture @pytest.fixture
def enable_schema_validation() -> bool: def enable_schema_validation() -> bool:
"""Fixture to control enabling of recorder's statistics table validation. """Fixture to control enabling of recorder's statistics table validation.
@ -1453,6 +1463,7 @@ async def async_test_recorder(
recorder_db_url: str, recorder_db_url: str,
enable_nightly_purge: bool, enable_nightly_purge: bool,
enable_statistics: bool, enable_statistics: bool,
enable_missing_statistics: bool,
enable_schema_validation: bool, enable_schema_validation: bool,
enable_migrate_context_ids: bool, enable_migrate_context_ids: bool,
enable_migrate_event_type_ids: bool, enable_migrate_event_type_ids: bool,
@ -1511,7 +1522,7 @@ async def async_test_recorder(
) )
compile_missing = ( compile_missing = (
recorder.Recorder._schedule_compile_missing_statistics recorder.Recorder._schedule_compile_missing_statistics
if enable_statistics if enable_missing_statistics
else None else None
) )
migrate_states_context_ids = ( migrate_states_context_ids = (