core/tests/components/statistics/test_sensor.py

916 lines
32 KiB
Python

"""The test for the statistics sensor platform."""
from datetime import datetime, timedelta
import statistics
import unittest
from unittest.mock import patch
import pytest
from homeassistant import config as hass_config
from homeassistant.components import recorder
from homeassistant.components.sensor import ATTR_STATE_CLASS, STATE_CLASS_MEASUREMENT
from homeassistant.components.statistics.sensor import DOMAIN, StatisticsSensor
from homeassistant.const import (
ATTR_UNIT_OF_MEASUREMENT,
SERVICE_RELOAD,
STATE_UNAVAILABLE,
STATE_UNKNOWN,
TEMP_CELSIUS,
)
from homeassistant.setup import async_setup_component, setup_component
from homeassistant.util import dt as dt_util
from tests.common import (
fire_time_changed,
get_fixture_path,
get_test_home_assistant,
init_recorder_component,
)
from tests.components.recorder.common import wait_recording_done
@pytest.fixture(autouse=True)
def mock_legacy_time(legacy_patchable_time):
"""Make time patchable for all the tests."""
yield
class TestStatisticsSensor(unittest.TestCase):
"""Test the Statistics sensor."""
def setup_method(self, method):
"""Set up things to be run when tests are started."""
self.hass = get_test_home_assistant()
self.values_binary = ["on", "off", "on", "off", "on", "off", "on"]
self.values = [17, 20, 15.2, 5, 3.8, 9.2, 6.7, 14, 6]
self.mean = round(sum(self.values) / len(self.values), 2)
self.addCleanup(self.hass.stop)
def test_sensor_defaults_binary(self):
"""Test the general behavior of the sensor, with binary source sensor."""
assert setup_component(
self.hass,
"sensor",
{
"sensor": [
{
"platform": "statistics",
"name": "test",
"entity_id": "binary_sensor.test_monitored",
},
{
"platform": "statistics",
"name": "test_unitless",
"entity_id": "binary_sensor.test_monitored_unitless",
},
]
},
)
self.hass.block_till_done()
self.hass.start()
self.hass.block_till_done()
for value in self.values_binary:
self.hass.states.set(
"binary_sensor.test_monitored",
value,
{ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS},
)
self.hass.states.set("binary_sensor.test_monitored_unitless", value)
self.hass.block_till_done()
state = self.hass.states.get("sensor.test")
assert state.state == str(len(self.values_binary))
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) is None
assert state.attributes.get(ATTR_STATE_CLASS) == STATE_CLASS_MEASUREMENT
assert state.attributes.get("buffer_usage_ratio") == round(7 / 20, 2)
assert state.attributes.get("source_value_valid") is True
assert "age_coverage_ratio" not in state.attributes
state = self.hass.states.get("sensor.test_unitless")
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) is None
def test_sensor_defaults_numeric(self):
"""Test the general behavior of the sensor, with numeric source sensor."""
assert setup_component(
self.hass,
"sensor",
{
"sensor": [
{
"platform": "statistics",
"name": "test",
"entity_id": "sensor.test_monitored",
},
]
},
)
self.hass.block_till_done()
self.hass.start()
self.hass.block_till_done()
for value in self.values:
self.hass.states.set(
"sensor.test_monitored",
value,
{ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS},
)
self.hass.block_till_done()
state = self.hass.states.get("sensor.test")
assert state.state == str(self.mean)
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == TEMP_CELSIUS
assert state.attributes.get(ATTR_STATE_CLASS) == STATE_CLASS_MEASUREMENT
assert state.attributes.get("buffer_usage_ratio") == round(9 / 20, 2)
assert state.attributes.get("source_value_valid") is True
assert "age_coverage_ratio" not in state.attributes
# Source sensor turns unavailable, then available with valid value,
# statistics sensor should follow
state = self.hass.states.get("sensor.test")
self.hass.states.set(
"sensor.test_monitored",
STATE_UNAVAILABLE,
)
self.hass.block_till_done()
new_state = self.hass.states.get("sensor.test")
assert new_state.state == STATE_UNAVAILABLE
assert new_state.attributes.get("source_value_valid") is None
self.hass.states.set(
"sensor.test_monitored",
0,
{ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS},
)
self.hass.block_till_done()
new_state = self.hass.states.get("sensor.test")
new_mean = round(sum(self.values) / (len(self.values) + 1), 2)
assert new_state.state == str(new_mean)
assert new_state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == TEMP_CELSIUS
assert new_state.attributes.get("buffer_usage_ratio") == round(10 / 20, 2)
assert new_state.attributes.get("source_value_valid") is True
# Source sensor has a nonnumerical state, unit and state should not change
state = self.hass.states.get("sensor.test")
self.hass.states.set("sensor.test_monitored", "beer", {})
self.hass.block_till_done()
new_state = self.hass.states.get("sensor.test")
assert new_state.state == str(new_mean)
assert new_state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == TEMP_CELSIUS
assert new_state.attributes.get("source_value_valid") is False
# Source sensor has the STATE_UNKNOWN state, unit and state should not change
state = self.hass.states.get("sensor.test")
self.hass.states.set("sensor.test_monitored", STATE_UNKNOWN, {})
self.hass.block_till_done()
new_state = self.hass.states.get("sensor.test")
assert new_state.state == str(new_mean)
assert new_state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == TEMP_CELSIUS
assert new_state.attributes.get("source_value_valid") is False
# Source sensor is removed, unit and state should not change
# This is equal to a None value being published
self.hass.states.remove("sensor.test_monitored")
self.hass.block_till_done()
new_state = self.hass.states.get("sensor.test")
assert new_state.state == str(new_mean)
assert new_state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == TEMP_CELSIUS
assert new_state.attributes.get("source_value_valid") is False
def test_sampling_size_non_default(self):
"""Test rotation."""
assert setup_component(
self.hass,
"sensor",
{
"sensor": [
{
"platform": "statistics",
"name": "test",
"entity_id": "sensor.test_monitored",
"sampling_size": 5,
},
]
},
)
self.hass.block_till_done()
self.hass.start()
self.hass.block_till_done()
for value in self.values:
self.hass.states.set(
"sensor.test_monitored",
value,
{ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS},
)
self.hass.block_till_done()
state = self.hass.states.get("sensor.test")
new_mean = round(sum(self.values[-5:]) / len(self.values[-5:]), 2)
assert state.state == str(new_mean)
assert state.attributes.get("buffer_usage_ratio") == round(5 / 5, 2)
def test_sampling_size_1(self):
"""Test validity of stats requiring only one sample."""
assert setup_component(
self.hass,
"sensor",
{
"sensor": [
{
"platform": "statistics",
"name": "test",
"entity_id": "sensor.test_monitored",
"sampling_size": 1,
},
]
},
)
self.hass.block_till_done()
self.hass.start()
self.hass.block_till_done()
for value in self.values[-3:]: # just the last 3 will do
self.hass.states.set(
"sensor.test_monitored",
value,
{ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS},
)
self.hass.block_till_done()
state = self.hass.states.get("sensor.test")
new_mean = float(self.values[-1])
assert state.state == str(new_mean)
assert state.attributes.get("buffer_usage_ratio") == round(1 / 1, 2)
def test_age_limit_expiry(self):
"""Test that values are removed after certain age."""
now = dt_util.utcnow()
mock_data = {
"return_time": datetime(now.year + 1, 8, 2, 12, 23, tzinfo=dt_util.UTC)
}
def mock_now():
return mock_data["return_time"]
with patch(
"homeassistant.components.statistics.sensor.dt_util.utcnow", new=mock_now
):
assert setup_component(
self.hass,
"sensor",
{
"sensor": [
{
"platform": "statistics",
"name": "test",
"entity_id": "sensor.test_monitored",
"max_age": {"minutes": 4},
},
]
},
)
self.hass.block_till_done()
self.hass.start()
self.hass.block_till_done()
for value in self.values:
self.hass.states.set(
"sensor.test_monitored",
value,
{ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS},
)
self.hass.block_till_done()
mock_data["return_time"] += timedelta(minutes=1)
# After adding all values, we should only see 5 values in memory
state = self.hass.states.get("sensor.test")
new_mean = round(sum(self.values[-5:]) / len(self.values[-5:]), 2)
assert state.state == str(new_mean)
assert state.attributes.get("buffer_usage_ratio") == round(5 / 20, 2)
assert state.attributes.get("age_coverage_ratio") == 1.0
# Values expire over time. Only two are left
mock_data["return_time"] += timedelta(minutes=2)
fire_time_changed(self.hass, mock_data["return_time"])
self.hass.block_till_done()
state = self.hass.states.get("sensor.test")
new_mean = round(sum(self.values[-2:]) / len(self.values[-2:]), 2)
assert state.state == str(new_mean)
assert state.attributes.get("buffer_usage_ratio") == round(2 / 20, 2)
assert state.attributes.get("age_coverage_ratio") == 1 / 4
# Values expire over time. Only one is left
mock_data["return_time"] += timedelta(minutes=1)
fire_time_changed(self.hass, mock_data["return_time"])
self.hass.block_till_done()
state = self.hass.states.get("sensor.test")
new_mean = float(self.values[-1])
assert state.state == str(new_mean)
assert state.attributes.get("buffer_usage_ratio") == round(1 / 20, 2)
assert state.attributes.get("age_coverage_ratio") == 0
# Values expire over time. Memory is empty
mock_data["return_time"] += timedelta(minutes=1)
fire_time_changed(self.hass, mock_data["return_time"])
self.hass.block_till_done()
state = self.hass.states.get("sensor.test")
assert state.state == STATE_UNKNOWN
assert state.attributes.get("buffer_usage_ratio") == round(0 / 20, 2)
assert state.attributes.get("age_coverage_ratio") == STATE_UNKNOWN
def test_precision_0(self):
"""Test correct result with precision=0 as integer."""
assert setup_component(
self.hass,
"sensor",
{
"sensor": [
{
"platform": "statistics",
"name": "test",
"entity_id": "sensor.test_monitored",
"precision": 0,
},
]
},
)
self.hass.block_till_done()
self.hass.start()
self.hass.block_till_done()
for value in self.values:
self.hass.states.set(
"sensor.test_monitored",
value,
{ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS},
)
self.hass.block_till_done()
state = self.hass.states.get("sensor.test")
assert state.state == str(int(round(self.mean)))
def test_precision_1(self):
"""Test correct result with precision=1 rounded to one decimal."""
assert setup_component(
self.hass,
"sensor",
{
"sensor": [
{
"platform": "statistics",
"name": "test",
"entity_id": "sensor.test_monitored",
"precision": 1,
},
]
},
)
self.hass.block_till_done()
self.hass.start()
self.hass.block_till_done()
for value in self.values:
self.hass.states.set(
"sensor.test_monitored",
value,
{ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS},
)
self.hass.block_till_done()
state = self.hass.states.get("sensor.test")
assert state.state == str(round(sum(self.values) / len(self.values), 1))
def test_state_class(self):
"""Test state class, which depends on the characteristic configured."""
assert setup_component(
self.hass,
"sensor",
{
"sensor": [
{
"platform": "statistics",
"name": "test_normal",
"entity_id": "sensor.test_monitored",
"state_characteristic": "count",
},
{
"platform": "statistics",
"name": "test_nan",
"entity_id": "sensor.test_monitored",
"state_characteristic": "datetime_oldest",
},
]
},
)
self.hass.block_till_done()
self.hass.start()
self.hass.block_till_done()
for value in self.values:
self.hass.states.set(
"sensor.test_monitored",
value,
{ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS},
)
self.hass.block_till_done()
state = self.hass.states.get("sensor.test_normal")
assert state.attributes.get(ATTR_STATE_CLASS) == STATE_CLASS_MEASUREMENT
state = self.hass.states.get("sensor.test_nan")
assert state.attributes.get(ATTR_STATE_CLASS) is None
def test_unitless_source_sensor(self):
"""Statistics for a unitless source sensor should never have a unit."""
assert setup_component(
self.hass,
"sensor",
{
"sensor": [
{
"platform": "statistics",
"name": "test_unitless_1",
"entity_id": "sensor.test_monitored_unitless",
"state_characteristic": "count",
},
{
"platform": "statistics",
"name": "test_unitless_2",
"entity_id": "sensor.test_monitored_unitless",
"state_characteristic": "mean",
},
{
"platform": "statistics",
"name": "test_unitless_3",
"entity_id": "sensor.test_monitored_unitless",
"state_characteristic": "change_second",
},
]
},
)
self.hass.block_till_done()
self.hass.start()
self.hass.block_till_done()
for value in self.values:
self.hass.states.set(
"sensor.test_monitored_unitless",
value,
)
self.hass.block_till_done()
state = self.hass.states.get("sensor.test_unitless_1")
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) is None
state = self.hass.states.get("sensor.test_unitless_2")
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) is None
state = self.hass.states.get("sensor.test_unitless_3")
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) is None
def test_state_characteristics(self):
"""Test configured state characteristic for value and unit."""
now = dt_util.utcnow()
mock_data = {
"return_time": datetime(now.year + 1, 8, 2, 12, 23, 42, tzinfo=dt_util.UTC)
}
def mock_now():
return mock_data["return_time"]
value_spacing_minutes = 1
characteristics = (
{
"name": "average_linear",
"value_0": STATE_UNKNOWN,
"value_1": STATE_UNKNOWN,
"value_9": 10.68,
"unit": "°C",
},
{
"name": "average_step",
"value_0": STATE_UNKNOWN,
"value_1": STATE_UNKNOWN,
"value_9": 11.36,
"unit": "°C",
},
{
"name": "average_timeless",
"value_0": STATE_UNKNOWN,
"value_1": float(self.values[0]),
"value_9": float(self.mean),
"unit": "°C",
},
{
"name": "change",
"value_0": STATE_UNKNOWN,
"value_1": float(0),
"value_9": float(round(self.values[-1] - self.values[0], 2)),
"unit": "°C",
},
{
"name": "change_sample",
"value_0": STATE_UNKNOWN,
"value_1": STATE_UNKNOWN,
"value_9": float(
round(
(self.values[-1] - self.values[0]) / (len(self.values) - 1), 2
)
),
"unit": "°C/sample",
},
{
"name": "change_second",
"value_0": STATE_UNKNOWN,
"value_1": STATE_UNKNOWN,
"value_9": float(
round(
(self.values[-1] - self.values[0])
/ (60 * (len(self.values) - 1)),
2,
)
),
"unit": "°C/s",
},
{
"name": "count",
"value_0": 0,
"value_1": 1,
"value_9": len(self.values),
"unit": None,
},
{
"name": "datetime_newest",
"value_0": STATE_UNKNOWN,
"value_1": datetime(
now.year + 1,
8,
2,
12,
23 + len(self.values) + 10,
42,
tzinfo=dt_util.UTC,
),
"value_9": datetime(
now.year + 1,
8,
2,
12,
23 + len(self.values) - 1,
42,
tzinfo=dt_util.UTC,
),
"unit": None,
},
{
"name": "datetime_oldest",
"value_0": STATE_UNKNOWN,
"value_1": datetime(
now.year + 1,
8,
2,
12,
23 + len(self.values) + 10,
42,
tzinfo=dt_util.UTC,
),
"value_9": datetime(now.year + 1, 8, 2, 12, 23, 42, tzinfo=dt_util.UTC),
"unit": None,
},
{
"name": "distance_95_percent_of_values",
"value_0": STATE_UNKNOWN,
"value_1": STATE_UNKNOWN,
"value_9": float(round(2 * 1.96 * statistics.stdev(self.values), 2)),
"unit": "°C",
},
{
"name": "distance_99_percent_of_values",
"value_0": STATE_UNKNOWN,
"value_1": STATE_UNKNOWN,
"value_9": float(round(2 * 2.58 * statistics.stdev(self.values), 2)),
"unit": "°C",
},
{
"name": "distance_absolute",
"value_0": STATE_UNKNOWN,
"value_1": float(0),
"value_9": float(max(self.values) - min(self.values)),
"unit": "°C",
},
{
"name": "mean",
"value_0": STATE_UNKNOWN,
"value_1": float(self.values[0]),
"value_9": float(self.mean),
"unit": "°C",
},
{
"name": "median",
"value_0": STATE_UNKNOWN,
"value_1": float(self.values[0]),
"value_9": float(round(statistics.median(self.values), 2)),
"unit": "°C",
},
{
"name": "noisiness",
"value_0": STATE_UNKNOWN,
"value_1": STATE_UNKNOWN,
"value_9": float(
round(sum([3, 4.8, 10.2, 1.2, 5.4, 2.5, 7.3, 8]) / 8, 2)
),
"unit": "°C",
},
{
"name": "quantiles",
"value_0": STATE_UNKNOWN,
"value_1": STATE_UNKNOWN,
"value_9": [
round(quantile, 2) for quantile in statistics.quantiles(self.values)
],
"unit": None,
},
{
"name": "standard_deviation",
"value_0": STATE_UNKNOWN,
"value_1": STATE_UNKNOWN,
"value_9": float(round(statistics.stdev(self.values), 2)),
"unit": "°C",
},
{
"name": "total",
"value_0": STATE_UNKNOWN,
"value_1": float(self.values[0]),
"value_9": float(sum(self.values)),
"unit": "°C",
},
{
"name": "value_max",
"value_0": STATE_UNKNOWN,
"value_1": float(self.values[0]),
"value_9": float(max(self.values)),
"unit": "°C",
},
{
"name": "value_min",
"value_0": STATE_UNKNOWN,
"value_1": float(self.values[0]),
"value_9": float(min(self.values)),
"unit": "°C",
},
{
"name": "variance",
"value_0": STATE_UNKNOWN,
"value_1": STATE_UNKNOWN,
"value_9": float(round(statistics.variance(self.values), 2)),
"unit": "°C²",
},
)
sensors_config = []
for characteristic in characteristics:
sensors_config.append(
{
"platform": "statistics",
"name": "test_" + characteristic["name"],
"entity_id": "sensor.test_monitored",
"state_characteristic": characteristic["name"],
"max_age": {"minutes": 10},
}
)
with patch(
"homeassistant.components.statistics.sensor.dt_util.utcnow", new=mock_now
):
assert setup_component(
self.hass,
"sensor",
{"sensor": sensors_config},
)
self.hass.block_till_done()
self.hass.start()
self.hass.block_till_done()
# With all values in buffer
for value in self.values:
self.hass.states.set(
"sensor.test_monitored",
value,
{ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS},
)
self.hass.block_till_done()
mock_data["return_time"] += timedelta(minutes=value_spacing_minutes)
for characteristic in characteristics:
state = self.hass.states.get("sensor.test_" + characteristic["name"])
assert state.state == str(characteristic["value_9"]), (
f"value mismatch for characteristic '{characteristic['name']}' (buffer filled) "
f"- assert {state.state} == {str(characteristic['value_9'])}"
)
assert (
state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
== characteristic["unit"]
), f"unit mismatch for characteristic '{characteristic['name']}'"
# With empty buffer
mock_data["return_time"] += timedelta(minutes=10)
fire_time_changed(self.hass, mock_data["return_time"])
self.hass.block_till_done()
for characteristic in characteristics:
state = self.hass.states.get("sensor.test_" + characteristic["name"])
assert state.state == str(characteristic["value_0"]), (
f"value mismatch for characteristic '{characteristic['name']}' (buffer empty) "
f"- assert {state.state} == {str(characteristic['value_0'])}"
)
# With single value in buffer
self.hass.states.set(
"sensor.test_monitored",
self.values[0],
{ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS},
)
self.hass.block_till_done()
mock_data["return_time"] += timedelta(minutes=1)
for characteristic in characteristics:
state = self.hass.states.get("sensor.test_" + characteristic["name"])
assert state.state == str(characteristic["value_1"]), (
f"value mismatch for characteristic '{characteristic['name']}' (one stored value) "
f"- assert {state.state} == {str(characteristic['value_1'])}"
)
def test_initialize_from_database(self):
"""Test initializing the statistics from the database."""
# enable the recorder
init_recorder_component(self.hass)
self.hass.block_till_done()
self.hass.data[recorder.DATA_INSTANCE].block_till_done()
# store some values
for value in self.values:
self.hass.states.set(
"sensor.test_monitored",
value,
{ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS},
)
self.hass.block_till_done()
# wait for the recorder to really store the data
wait_recording_done(self.hass)
# only now create the statistics component, so that it must read the
# data from the database
assert setup_component(
self.hass,
"sensor",
{
"sensor": [
{
"platform": "statistics",
"name": "test",
"entity_id": "sensor.test_monitored",
"sampling_size": 100,
},
]
},
)
self.hass.block_till_done()
self.hass.start()
self.hass.block_till_done()
# check if the result is as in test_sensor_source()
state = self.hass.states.get("sensor.test")
assert str(self.mean) == state.state
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == TEMP_CELSIUS
def test_initialize_from_database_with_maxage(self):
"""Test initializing the statistics from the database."""
now = dt_util.utcnow()
mock_data = {
"return_time": datetime(now.year + 1, 8, 2, 12, 23, 42, tzinfo=dt_util.UTC)
}
def mock_now():
return mock_data["return_time"]
# Testing correct retrieval from recorder, thus we do not
# want purging to occur within the class itself.
def mock_purge(self):
return
# enable the recorder
init_recorder_component(self.hass)
self.hass.block_till_done()
self.hass.data[recorder.DATA_INSTANCE].block_till_done()
with patch(
"homeassistant.components.statistics.sensor.dt_util.utcnow", new=mock_now
), patch.object(StatisticsSensor, "_purge_old", mock_purge):
# store some values
for value in self.values:
self.hass.states.set(
"sensor.test_monitored",
value,
{ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS},
)
self.hass.block_till_done()
# insert the next value 1 hour later
mock_data["return_time"] += timedelta(hours=1)
# wait for the recorder to really store the data
wait_recording_done(self.hass)
# only now create the statistics component, so that it must read
# the data from the database
assert setup_component(
self.hass,
"sensor",
{
"sensor": [
{
"platform": "statistics",
"name": "test",
"entity_id": "sensor.test_monitored",
"sampling_size": 100,
"state_characteristic": "datetime_newest",
"max_age": {"hours": 3},
},
]
},
)
self.hass.block_till_done()
self.hass.block_till_done()
self.hass.start()
self.hass.block_till_done()
# check if the result is as in test_sensor_source()
state = self.hass.states.get("sensor.test")
assert state.attributes.get("age_coverage_ratio") == round(2 / 3, 2)
# The max_age timestamp should be 1 hour before what we have right
# now in mock_data['return_time'].
assert mock_data["return_time"] == datetime.strptime(
state.state, "%Y-%m-%d %H:%M:%S%z"
) + timedelta(hours=1)
async def test_reload(hass):
"""Verify we can reload filter sensors."""
await hass.async_add_executor_job(
init_recorder_component, hass
) # force in memory db
hass.states.async_set("sensor.test_monitored", 12345)
await async_setup_component(
hass,
"sensor",
{
"sensor": [
{
"platform": "statistics",
"name": "test",
"entity_id": "sensor.test_monitored",
"sampling_size": 100,
},
]
},
)
await hass.async_block_till_done()
await hass.async_start()
await hass.async_block_till_done()
assert len(hass.states.async_all()) == 2
assert hass.states.get("sensor.test")
yaml_path = get_fixture_path("configuration.yaml", "statistics")
with patch.object(hass_config, "YAML_CONFIG_FILE", yaml_path):
await hass.services.async_call(
DOMAIN,
SERVICE_RELOAD,
{},
blocking=True,
)
await hass.async_block_till_done()
assert len(hass.states.async_all()) == 2
assert hass.states.get("sensor.test") is None
assert hass.states.get("sensor.cputest")