5454VALUES_NUMERIC = [17 , 20 , 15.2 , 5 , 3.8 , 9.2 , 6.7 , 14 , 6 ]
5555VALUES_NUMERIC_LINEAR = [1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ]
5656
57+ A1 = {"attr" : "value1" }
58+ A2 = {"attr" : "value2" }
59+
5760
5861async 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
309311async 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