Skip to content

Commit d72fb02

Browse files
authored
Improve statistics tests (home-assistant#148937)
1 parent 0e6a1e3 commit d72fb02

File tree

1 file changed

+65
-34
lines changed

1 file changed

+65
-34
lines changed

tests/components/statistics/test_sensor.py

Lines changed: 65 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@
5454
VALUES_NUMERIC = [17, 20, 15.2, 5, 3.8, 9.2, 6.7, 14, 6]
5555
VALUES_NUMERIC_LINEAR = [1, 2, 3, 4, 5, 6, 7, 8, 9]
5656

57+
A1 = {"attr": "value1"}
58+
A2 = {"attr": "value2"}
59+
5760

5861
async def test_unique_id(
5962
hass: HomeAssistant, entity_registry: er.EntityRegistry
@@ -249,7 +252,22 @@ async def test_sensor_defaults_binary(hass: HomeAssistant) -> None:
249252
assert "age_coverage_ratio" not in state.attributes
250253

251254

252-
async def test_sensor_state_reported(hass: HomeAssistant) -> None:
255+
@pytest.mark.parametrize("force_update", [True, False])
256+
@pytest.mark.parametrize(
257+
("values", "attributes"),
258+
[
259+
# Fires last reported events
260+
([18, 1, 1, 1, 1, 1, 1, 1, 9], [A1, A1, A1, A1, A1, A1, A1, A1, A1]),
261+
# Fires state change events
262+
([18, 1, 1, 1, 1, 1, 1, 1, 9], [A1, A2, A1, A2, A1, A2, A1, A2, A1]),
263+
],
264+
)
265+
async def test_sensor_state_updated_reported(
266+
hass: HomeAssistant,
267+
values: list[float],
268+
attributes: list[dict[str, Any]],
269+
force_update: bool,
270+
) -> None:
253271
"""Test the behavior of the sensor with a sequence of identical values.
254272
255273
Forced updates no longer make a difference, since the statistics are now reacting not
@@ -258,7 +276,6 @@ async def test_sensor_state_reported(hass: HomeAssistant) -> None:
258276
This fixes problems with time based averages and some other functions that behave
259277
differently when repeating values are reported.
260278
"""
261-
repeating_values = [18, 0, 0, 0, 0, 0, 0, 0, 9]
262279
assert await async_setup_component(
263280
hass,
264281
"sensor",
@@ -267,14 +284,7 @@ async def test_sensor_state_reported(hass: HomeAssistant) -> None:
267284
{
268285
"platform": "statistics",
269286
"name": "test_normal",
270-
"entity_id": "sensor.test_monitored_normal",
271-
"state_characteristic": "mean",
272-
"sampling_size": 20,
273-
},
274-
{
275-
"platform": "statistics",
276-
"name": "test_force",
277-
"entity_id": "sensor.test_monitored_force",
287+
"entity_id": "sensor.test_monitored",
278288
"state_characteristic": "mean",
279289
"sampling_size": 20,
280290
},
@@ -283,27 +293,19 @@ async def test_sensor_state_reported(hass: HomeAssistant) -> None:
283293
)
284294
await hass.async_block_till_done()
285295

286-
for value in repeating_values:
296+
for value, attribute in zip(values, attributes, strict=True):
287297
hass.states.async_set(
288-
"sensor.test_monitored_normal",
289-
str(value),
290-
{ATTR_UNIT_OF_MEASUREMENT: UnitOfTemperature.CELSIUS},
291-
)
292-
hass.states.async_set(
293-
"sensor.test_monitored_force",
298+
"sensor.test_monitored",
294299
str(value),
295-
{ATTR_UNIT_OF_MEASUREMENT: UnitOfTemperature.CELSIUS},
296-
force_update=True,
300+
{ATTR_UNIT_OF_MEASUREMENT: UnitOfTemperature.CELSIUS} | attribute,
301+
force_update=force_update,
297302
)
298303
await hass.async_block_till_done()
299304

300-
state_normal = hass.states.get("sensor.test_normal")
301-
state_force = hass.states.get("sensor.test_force")
302-
assert state_normal and state_force
303-
assert state_normal.state == str(round(sum(repeating_values) / 9, 2))
304-
assert state_force.state == str(round(sum(repeating_values) / 9, 2))
305-
assert state_normal.attributes.get("buffer_usage_ratio") == round(9 / 20, 2)
306-
assert state_force.attributes.get("buffer_usage_ratio") == round(9 / 20, 2)
305+
state = hass.states.get("sensor.test_normal")
306+
assert state
307+
assert state.state == str(round(sum(values) / 9, 2))
308+
assert state.attributes.get("buffer_usage_ratio") == round(9 / 20, 2)
307309

308310

309311
async def test_sampling_boundaries_given(hass: HomeAssistant) -> None:
@@ -1785,12 +1787,40 @@ def mock_state_changes_during_period(*args, **kwargs):
17851787
assert float(hass.states.get("sensor.test").state) == pytest.approx(4.5)
17861788

17871789

1788-
async def test_average_linear_unevenly_timed(hass: HomeAssistant) -> None:
1790+
@pytest.mark.parametrize("force_update", [True, False])
1791+
@pytest.mark.parametrize(
1792+
("values_attributes_and_times", "expected_state"),
1793+
[
1794+
(
1795+
# Fires last reported events
1796+
[(5.0, A1, 2), (10.0, A1, 1), (10.0, A1, 1), (10.0, A1, 2), (5.0, A1, 1)],
1797+
"8.33",
1798+
),
1799+
( # Fires state change events
1800+
[(5.0, A1, 2), (10.0, A2, 1), (10.0, A1, 1), (10.0, A2, 2), (5.0, A1, 1)],
1801+
"8.33",
1802+
),
1803+
(
1804+
# Fires last reported events
1805+
[(10.0, A1, 2), (10.0, A1, 1), (10.0, A1, 1), (10.0, A1, 2), (10.0, A1, 1)],
1806+
"10.0",
1807+
),
1808+
( # Fires state change events
1809+
[(10.0, A1, 2), (10.0, A2, 1), (10.0, A1, 1), (10.0, A2, 2), (10.0, A1, 1)],
1810+
"10.0",
1811+
),
1812+
],
1813+
)
1814+
async def test_average_linear_unevenly_timed(
1815+
hass: HomeAssistant,
1816+
force_update: bool,
1817+
values_attributes_and_times: list[tuple[float, dict[str, Any], float]],
1818+
expected_state: str,
1819+
) -> None:
17891820
"""Test the average_linear state characteristic with unevenly distributed values.
17901821
17911822
This also implicitly tests the correct timing of repeating values.
17921823
"""
1793-
values_and_times = [[5.0, 2], [10.0, 1], [10.0, 1], [10.0, 2], [5.0, 1]]
17941824

17951825
current_time = dt_util.utcnow()
17961826

@@ -1814,22 +1844,23 @@ async def test_average_linear_unevenly_timed(hass: HomeAssistant) -> None:
18141844
)
18151845
await hass.async_block_till_done()
18161846

1817-
for value_and_time in values_and_times:
1847+
for value, extra_attributes, time in values_attributes_and_times:
18181848
hass.states.async_set(
18191849
"sensor.test_monitored",
1820-
str(value_and_time[0]),
1821-
{ATTR_UNIT_OF_MEASUREMENT: DEGREE},
1850+
str(value),
1851+
{ATTR_UNIT_OF_MEASUREMENT: DEGREE} | extra_attributes,
1852+
force_update=force_update,
18221853
)
1823-
current_time += timedelta(seconds=value_and_time[1])
1854+
current_time += timedelta(seconds=time)
18241855
freezer.move_to(current_time)
18251856

18261857
await hass.async_block_till_done()
18271858

18281859
state = hass.states.get("sensor.test_sensor_average_linear")
18291860
assert state is not None
1830-
assert state.state == "8.33", (
1861+
assert state.state == expected_state, (
18311862
"value mismatch for characteristic 'sensor/average_linear' - "
1832-
f"assert {state.state} == 8.33"
1863+
f"assert {state.state} == {expected_state}"
18331864
)
18341865

18351866

0 commit comments

Comments
 (0)