Add statistics tests for sensor with changing device class (#57317)

This commit is contained in:
Erik Montnemery 2021-10-12 18:09:32 +02:00 committed by GitHub
parent 007af4a7aa
commit ffeb73a4f6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 181 additions and 1 deletions

View file

@ -463,9 +463,10 @@ def _compile_statistics( # noqa: C901
if entity_id not in hass.data[WARN_UNSTABLE_UNIT]:
hass.data[WARN_UNSTABLE_UNIT].add(entity_id)
_LOGGER.warning(
"The unit of %s (%s) does not match the unit of already "
"The %sunit of %s (%s) does not match the unit of already "
"compiled statistics (%s). Generation of long term statistics "
"will be suppressed unless the unit changes back to %s",
"normalized " if device_class in DEVICE_CLASS_UNITS else "",
entity_id,
unit,
old_metadata[1]["unit_of_measurement"],

View file

@ -1705,6 +1705,185 @@ def test_compile_hourly_statistics_changing_units_3(
assert "Error while processing event StatisticsTask" not in caplog.text
@pytest.mark.parametrize(
"device_class,state_unit,statistic_unit,mean,min,max",
[
("power", "kW", "W", 13.050847, -10, 30),
],
)
def test_compile_hourly_statistics_changing_device_class_1(
hass_recorder, caplog, device_class, state_unit, statistic_unit, mean, min, max
):
"""Test compiling hourly statistics where device class changes from one hour to the next."""
zero = dt_util.utcnow()
hass = hass_recorder()
recorder = hass.data[DATA_INSTANCE]
setup_component(hass, "sensor", {})
# Record some states for an initial period, the entity has no device class
attributes = {
"state_class": "measurement",
"unit_of_measurement": state_unit,
}
four, states = record_states(hass, zero, "sensor.test1", attributes)
recorder.do_adhoc_statistics(start=zero)
wait_recording_done(hass)
assert "does not match the unit of already compiled" not in caplog.text
statistic_ids = list_statistic_ids(hass)
assert statistic_ids == [
{"statistic_id": "sensor.test1", "unit_of_measurement": state_unit}
]
stats = statistics_during_period(hass, zero, period="5minute")
assert stats == {
"sensor.test1": [
{
"statistic_id": "sensor.test1",
"start": process_timestamp_to_utc_isoformat(zero),
"end": process_timestamp_to_utc_isoformat(zero + timedelta(minutes=5)),
"mean": approx(mean),
"min": approx(min),
"max": approx(max),
"last_reset": None,
"state": None,
"sum": None,
}
]
}
# Update device class and record additional states
attributes["device_class"] = device_class
four, _states = record_states(
hass, zero + timedelta(minutes=5), "sensor.test1", attributes
)
states["sensor.test1"] += _states["sensor.test1"]
four, _states = record_states(
hass, zero + timedelta(minutes=10), "sensor.test1", attributes
)
states["sensor.test1"] += _states["sensor.test1"]
hist = history.get_significant_states(hass, zero, four)
assert dict(states) == dict(hist)
# Run statistics again, we get a warning, and no additional statistics is generated
recorder.do_adhoc_statistics(start=zero + timedelta(minutes=10))
wait_recording_done(hass)
assert (
f"The normalized unit of sensor.test1 ({statistic_unit}) does not match the "
f"unit of already compiled statistics ({state_unit})" in caplog.text
)
statistic_ids = list_statistic_ids(hass)
assert statistic_ids == [
{"statistic_id": "sensor.test1", "unit_of_measurement": state_unit}
]
stats = statistics_during_period(hass, zero, period="5minute")
assert stats == {
"sensor.test1": [
{
"statistic_id": "sensor.test1",
"start": process_timestamp_to_utc_isoformat(zero),
"end": process_timestamp_to_utc_isoformat(zero + timedelta(minutes=5)),
"mean": approx(mean),
"min": approx(min),
"max": approx(max),
"last_reset": None,
"state": None,
"sum": None,
}
]
}
assert "Error while processing event StatisticsTask" not in caplog.text
@pytest.mark.parametrize(
"device_class,state_unit,statistic_unit,mean,min,max",
[
("power", "kW", "W", 13050.847, -10000, 30000),
],
)
def test_compile_hourly_statistics_changing_device_class_2(
hass_recorder, caplog, device_class, state_unit, statistic_unit, mean, min, max
):
"""Test compiling hourly statistics where device class changes from one hour to the next."""
zero = dt_util.utcnow()
hass = hass_recorder()
recorder = hass.data[DATA_INSTANCE]
setup_component(hass, "sensor", {})
# Record some states for an initial period, the entity has a device class
attributes = {
"device_class": device_class,
"state_class": "measurement",
"unit_of_measurement": state_unit,
}
four, states = record_states(hass, zero, "sensor.test1", attributes)
recorder.do_adhoc_statistics(start=zero)
wait_recording_done(hass)
assert "does not match the unit of already compiled" not in caplog.text
statistic_ids = list_statistic_ids(hass)
assert statistic_ids == [
{"statistic_id": "sensor.test1", "unit_of_measurement": statistic_unit}
]
stats = statistics_during_period(hass, zero, period="5minute")
assert stats == {
"sensor.test1": [
{
"statistic_id": "sensor.test1",
"start": process_timestamp_to_utc_isoformat(zero),
"end": process_timestamp_to_utc_isoformat(zero + timedelta(minutes=5)),
"mean": approx(mean),
"min": approx(min),
"max": approx(max),
"last_reset": None,
"state": None,
"sum": None,
}
]
}
# Remove device class and record additional states
attributes.pop("device_class")
four, _states = record_states(
hass, zero + timedelta(minutes=5), "sensor.test1", attributes
)
states["sensor.test1"] += _states["sensor.test1"]
four, _states = record_states(
hass, zero + timedelta(minutes=10), "sensor.test1", attributes
)
states["sensor.test1"] += _states["sensor.test1"]
hist = history.get_significant_states(hass, zero, four)
assert dict(states) == dict(hist)
# Run statistics again, we get a warning, and no additional statistics is generated
recorder.do_adhoc_statistics(start=zero + timedelta(minutes=10))
wait_recording_done(hass)
assert (
f"The unit of sensor.test1 ({state_unit}) does not match the "
f"unit of already compiled statistics ({statistic_unit})" in caplog.text
)
statistic_ids = list_statistic_ids(hass)
assert statistic_ids == [
{"statistic_id": "sensor.test1", "unit_of_measurement": statistic_unit}
]
stats = statistics_during_period(hass, zero, period="5minute")
assert stats == {
"sensor.test1": [
{
"statistic_id": "sensor.test1",
"start": process_timestamp_to_utc_isoformat(zero),
"end": process_timestamp_to_utc_isoformat(zero + timedelta(minutes=5)),
"mean": approx(mean),
"min": approx(min),
"max": approx(max),
"last_reset": None,
"state": None,
"sum": None,
}
]
}
assert "Error while processing event StatisticsTask" not in caplog.text
@pytest.mark.parametrize(
"device_class,unit,native_unit,mean,min,max",
[