From 8ef7cae36d898f6943f62c09ad08985689d6f2a7 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Mon, 23 Sep 2024 12:50:40 +0200 Subject: [PATCH] Speedup Reolink tests by using scope="module" (#125215) * use scope="module" * Instead of side_effect = None, use reset_mock(side_efffect=True) * fix tests --- tests/components/reolink/conftest.py | 2 +- tests/components/reolink/test_button.py | 6 ++++ tests/components/reolink/test_camera.py | 2 ++ tests/components/reolink/test_config_flow.py | 11 ++++++- tests/components/reolink/test_host.py | 33 +++++++++++++++---- tests/components/reolink/test_init.py | 16 +++++++++ tests/components/reolink/test_light.py | 6 ++++ tests/components/reolink/test_media_source.py | 5 +++ tests/components/reolink/test_number.py | 4 +++ tests/components/reolink/test_select.py | 6 ++++ tests/components/reolink/test_siren.py | 6 +++- tests/components/reolink/test_switch.py | 13 ++++++-- tests/components/reolink/test_update.py | 3 ++ 13 files changed, 101 insertions(+), 12 deletions(-) diff --git a/tests/components/reolink/conftest.py b/tests/components/reolink/conftest.py index c14a5ee0c32..720ee362c3c 100644 --- a/tests/components/reolink/conftest.py +++ b/tests/components/reolink/conftest.py @@ -52,7 +52,7 @@ def mock_setup_entry() -> Generator[AsyncMock]: yield mock_setup_entry -@pytest.fixture +@pytest.fixture(scope="module") def reolink_connect_class() -> Generator[MagicMock]: """Mock reolink connection and return both the host_mock and host_mock_class.""" with ( diff --git a/tests/components/reolink/test_button.py b/tests/components/reolink/test_button.py index 7c91051c66e..126fbb6b29a 100644 --- a/tests/components/reolink/test_button.py +++ b/tests/components/reolink/test_button.py @@ -48,6 +48,8 @@ async def test_button( blocking=True, ) + reolink_connect.set_ptz_command.reset_mock(side_effect=True) + async def test_ptz_move_service( hass: HomeAssistant, @@ -79,6 +81,8 @@ async def test_ptz_move_service( blocking=True, ) + reolink_connect.set_ptz_command.reset_mock(side_effect=True) + @pytest.mark.usefixtures("entity_registry_enabled_by_default") async def test_host_button( @@ -110,3 +114,5 @@ async def test_host_button( {ATTR_ENTITY_ID: entity_id}, blocking=True, ) + + reolink_connect.reboot.reset_mock(side_effect=True) diff --git a/tests/components/reolink/test_camera.py b/tests/components/reolink/test_camera.py index 96bb5a099c9..21ebb242882 100644 --- a/tests/components/reolink/test_camera.py +++ b/tests/components/reolink/test_camera.py @@ -43,6 +43,8 @@ async def test_camera( # check getting the stream source assert await async_get_stream_source(hass, entity_id) is not None + reolink_connect.get_snapshot.reset_mock(side_effect=True) + @pytest.mark.usefixtures("entity_registry_enabled_by_default") async def test_camera_no_stream_source( diff --git a/tests/components/reolink/test_config_flow.py b/tests/components/reolink/test_config_flow.py index 4d89906a768..4ade0771ffb 100644 --- a/tests/components/reolink/test_config_flow.py +++ b/tests/components/reolink/test_config_flow.py @@ -200,7 +200,7 @@ async def test_config_flow_errors( assert result["step_id"] == "user" assert result["errors"] == {CONF_HOST: "api_error"} - reolink_connect.get_host_data.side_effect = None + reolink_connect.get_host_data.reset_mock(side_effect=True) result = await hass.config_entries.flow.async_configure( result["flow_id"], { @@ -225,6 +225,9 @@ async def test_config_flow_errors( CONF_PROTOCOL: DEFAULT_PROTOCOL, } + reolink_connect.unsubscribe.reset_mock(side_effect=True) + reolink_connect.logout.reset_mock(side_effect=True) + async def test_options_flow(hass: HomeAssistant, mock_setup_entry: MagicMock) -> None: """Test specifying non default settings using options flow.""" @@ -478,6 +481,7 @@ async def test_dhcp_ip_update( ) if attr is not None: + original = getattr(reolink_connect, attr) setattr(reolink_connect, attr, value) result = await hass.config_entries.flow.async_init( @@ -508,6 +512,11 @@ async def test_dhcp_ip_update( await hass.async_block_till_done() assert config_entry.data[CONF_HOST] == expected + reolink_connect.get_states.side_effect = None + reolink_connect_class.reset_mock() + if attr is not None: + setattr(reolink_connect, attr, original) + async def test_reconfig(hass: HomeAssistant, mock_setup_entry: MagicMock) -> None: """Test a reconfiguration flow.""" diff --git a/tests/components/reolink/test_host.py b/tests/components/reolink/test_host.py index 639d5bf046f..77d156c9486 100644 --- a/tests/components/reolink/test_host.py +++ b/tests/components/reolink/test_host.py @@ -75,9 +75,7 @@ async def test_webhook_callback( # test webhook callback single channel with error in event callback signal_ch.reset_mock() - reolink_connect.ONVIF_event_callback = AsyncMock( - side_effect=Exception("Test error") - ) + reolink_connect.ONVIF_event_callback.side_effect = Exception("Test error") await client.post(f"/api/webhook/{webhook_id}", data="test_data") signal_ch.assert_not_called() @@ -87,19 +85,22 @@ async def test_webhook_callback( content=bytes("test", "utf-8"), mock_source="test", ) - request.read = AsyncMock(side_effect=ConnectionResetError("Test error")) + request.read = AsyncMock() + request.read.side_effect = ConnectionResetError("Test error") await async_handle_webhook(hass, webhook_id, request) signal_all.assert_not_called() - request.read = AsyncMock(side_effect=ClientResponseError("Test error", "Test")) + request.read.side_effect = ClientResponseError("Test error", "Test") await async_handle_webhook(hass, webhook_id, request) signal_all.assert_not_called() - request.read = AsyncMock(side_effect=CancelledError("Test error")) + request.read.side_effect = CancelledError("Test error") with pytest.raises(CancelledError): await async_handle_webhook(hass, webhook_id, request) signal_all.assert_not_called() + reolink_connect.ONVIF_event_callback.reset_mock(side_effect=True) + async def test_no_mac( hass: HomeAssistant, @@ -107,11 +108,14 @@ async def test_no_mac( reolink_connect: MagicMock, ) -> None: """Test setup of host with no mac.""" + original = reolink_connect.mac_address reolink_connect.mac_address = None assert not await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() assert config_entry.state is ConfigEntryState.SETUP_RETRY + reolink_connect.mac_address = original + async def test_subscribe_error( hass: HomeAssistant, @@ -124,6 +128,7 @@ async def test_subscribe_error( assert await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() assert config_entry.state is ConfigEntryState.LOADED + reolink_connect.subscribe.reset_mock(side_effect=True) async def test_subscribe_unsuccesfull( @@ -179,6 +184,9 @@ async def test_ONVIF_not_supported( await hass.async_block_till_done() assert config_entry.state is ConfigEntryState.LOADED + reolink_connect.subscribe.reset_mock(side_effect=True) + reolink_connect.subscribed.return_value = True + async def test_renew( hass: HomeAssistant, @@ -216,6 +224,9 @@ async def test_renew( reolink_connect.subscribe.assert_called() + reolink_connect.renew.reset_mock(side_effect=True) + reolink_connect.subscribe.reset_mock(side_effect=True) + async def test_long_poll_renew_fail( hass: HomeAssistant, @@ -237,6 +248,8 @@ async def test_long_poll_renew_fail( # ensure long polling continues reolink_connect.pull_point_request.assert_called() + reolink_connect.subscribe.reset_mock(side_effect=True) + async def test_register_webhook_errors( hass: HomeAssistant, @@ -290,6 +303,8 @@ async def test_long_poll_errors( reolink_connect: MagicMock, ) -> None: """Test errors during ONVIF long polling.""" + reolink_connect.pull_point_request.reset_mock() + assert await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() assert config_entry.state is ConfigEntryState.LOADED @@ -314,6 +329,8 @@ async def test_long_poll_errors( reolink_connect.unsubscribe.assert_called_with(sub_type=SubType.long_poll) + reolink_connect.pull_point_request.reset_mock(side_effect=True) + async def test_fast_polling_errors( hass: HomeAssistant, @@ -322,6 +339,7 @@ async def test_fast_polling_errors( reolink_connect: MagicMock, ) -> None: """Test errors during ONVIF fast polling.""" + reolink_connect.get_motion_state_all_ch.reset_mock() reolink_connect.get_motion_state_all_ch.side_effect = ReolinkError("Test error") reolink_connect.pull_point_request.side_effect = ReolinkError("Test error") @@ -348,6 +366,9 @@ async def test_fast_polling_errors( # fast polling continues despite errors assert reolink_connect.get_motion_state_all_ch.call_count == 2 + reolink_connect.get_motion_state_all_ch.reset_mock(side_effect=True) + reolink_connect.pull_point_request.reset_mock(side_effect=True) + async def test_diagnostics_event_connection( hass: HomeAssistant, diff --git a/tests/components/reolink/test_init.py b/tests/components/reolink/test_init.py index 765b3426249..ffb2dfca6bc 100644 --- a/tests/components/reolink/test_init.py +++ b/tests/components/reolink/test_init.py @@ -92,6 +92,7 @@ async def test_failures_parametrized( expected: ConfigEntryState, ) -> None: """Test outcomes when changing errors.""" + original = getattr(reolink_connect, attr) setattr(reolink_connect, attr, value) assert await hass.config_entries.async_setup(config_entry.entry_id) is ( expected is ConfigEntryState.LOADED @@ -100,6 +101,8 @@ async def test_failures_parametrized( assert config_entry.state == expected + setattr(reolink_connect, attr, original) + async def test_firmware_error_twice( hass: HomeAssistant, @@ -124,6 +127,8 @@ async def test_firmware_error_twice( assert hass.states.get(entity_id).state == STATE_UNAVAILABLE + reolink_connect.check_new_firmware.reset_mock(side_effect=True) + async def test_credential_error_three( hass: HomeAssistant, @@ -149,6 +154,8 @@ async def test_credential_error_three( assert (HOMEASSISTANT_DOMAIN, issue_id) in issue_registry.issues + reolink_connect.get_states.reset_mock(side_effect=True) + async def test_entry_reloading( hass: HomeAssistant, @@ -157,6 +164,7 @@ async def test_entry_reloading( ) -> None: """Test the entry is reloaded correctly when settings change.""" reolink_connect.is_nvr = False + reolink_connect.logout.reset_mock() assert await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() @@ -169,6 +177,8 @@ async def test_entry_reloading( assert reolink_connect.logout.call_count == 1 assert config_entry.title == "New Name" + reolink_connect.is_nvr = True + @pytest.mark.parametrize( ("attr", "value", "expected_models"), @@ -224,6 +234,7 @@ async def test_removing_disconnected_cams( # Try to remove the device after 'disconnecting' a camera. if attr is not None: + original = getattr(reolink_connect, attr) setattr(reolink_connect, attr, value) expected_success = TEST_CAM_MODEL not in expected_models for device in device_entries: @@ -237,6 +248,9 @@ async def test_removing_disconnected_cams( device_models = [device.model for device in device_entries] assert sorted(device_models) == sorted(expected_models) + if attr is not None: + setattr(reolink_connect, attr, original) + @pytest.mark.parametrize( ("attr", "value", "expected_models"), @@ -548,6 +562,8 @@ async def test_port_repair_issue( assert (DOMAIN, "enable_port") in issue_registry.issues + reolink_connect.set_net_port.reset_mock(side_effect=True) + async def test_webhook_repair_issue( hass: HomeAssistant, diff --git a/tests/components/reolink/test_light.py b/tests/components/reolink/test_light.py index 7c0c11c3f63..948a7fce0fe 100644 --- a/tests/components/reolink/test_light.py +++ b/tests/components/reolink/test_light.py @@ -94,6 +94,8 @@ async def test_light_turn_off( blocking=True, ) + reolink_connect.set_whiteled.reset_mock(side_effect=True) + async def test_light_turn_on( hass: HomeAssistant, @@ -145,6 +147,8 @@ async def test_light_turn_on( blocking=True, ) + reolink_connect.set_whiteled.reset_mock(side_effect=True) + async def test_host_light_state( hass: HomeAssistant, @@ -203,6 +207,8 @@ async def test_host_light_turn_off( blocking=True, ) + reolink_connect.set_state_light.reset_mock(side_effect=True) + async def test_host_light_turn_on( hass: HomeAssistant, diff --git a/tests/components/reolink/test_media_source.py b/tests/components/reolink/test_media_source.py index 494432d0412..32afd1f73ca 100644 --- a/tests/components/reolink/test_media_source.py +++ b/tests/components/reolink/test_media_source.py @@ -32,6 +32,7 @@ from homeassistant.setup import async_setup_component from .conftest import ( TEST_HOST2, + TEST_HOST_MODEL, TEST_MAC2, TEST_NVR_NAME, TEST_NVR_NAME2, @@ -225,6 +226,8 @@ async def test_browsing( assert browse.identifier == browse_files_id assert browse.children[0].identifier == browse_file_id + reolink_connect.model = TEST_HOST_MODEL + async def test_browsing_unsupported_encoding( hass: HomeAssistant, @@ -345,3 +348,5 @@ async def test_browsing_not_loaded( assert browse.title == "Reolink" assert browse.identifier is None assert len(browse.children) == 1 + + reolink_connect.get_host_data.side_effect = None diff --git a/tests/components/reolink/test_number.py b/tests/components/reolink/test_number.py index 89b6935de5b..c6507fa36c1 100644 --- a/tests/components/reolink/test_number.py +++ b/tests/components/reolink/test_number.py @@ -64,6 +64,8 @@ async def test_number( blocking=True, ) + reolink_connect.set_volume.reset_mock(side_effect=True) + async def test_host_number( hass: HomeAssistant, @@ -153,3 +155,5 @@ async def test_chime_number( {ATTR_ENTITY_ID: entity_id, ATTR_VALUE: 1}, blocking=True, ) + + test_chime.set_option.reset_mock(side_effect=True) diff --git a/tests/components/reolink/test_select.py b/tests/components/reolink/test_select.py index 0534f36f4c5..7910174380a 100644 --- a/tests/components/reolink/test_select.py +++ b/tests/components/reolink/test_select.py @@ -74,6 +74,8 @@ async def test_floodlight_mode_select( assert hass.states.get(entity_id).state == STATE_UNKNOWN + reolink_connect.set_whiteled.reset_mock(side_effect=True) + async def test_play_quick_reply_message( hass: HomeAssistant, @@ -99,6 +101,8 @@ async def test_play_quick_reply_message( ) reolink_connect.play_quick_reply.assert_called_once() + reolink_connect.quick_reply_dict = MagicMock() + async def test_chime_select( hass: HomeAssistant, @@ -153,3 +157,5 @@ async def test_chime_select( await hass.async_block_till_done() assert hass.states.get(entity_id).state == STATE_UNKNOWN + + test_chime.set_tone.reset_mock(side_effect=True) diff --git a/tests/components/reolink/test_siren.py b/tests/components/reolink/test_siren.py index 0d9d3e0b800..f6ba8e0ea77 100644 --- a/tests/components/reolink/test_siren.py +++ b/tests/components/reolink/test_siren.py @@ -61,7 +61,6 @@ async def test_siren( reolink_connect.set_siren.assert_called_with(0, True, 2) # test siren turn off - reolink_connect.set_siren.side_effect = None await hass.services.async_call( SIREN_DOMAIN, SERVICE_TURN_OFF, @@ -101,6 +100,7 @@ async def test_siren_turn_on_errors( entity_id = f"{Platform.SIREN}.{TEST_NVR_NAME}_siren" + original = getattr(reolink_connect, attr) setattr(reolink_connect, attr, value) with pytest.raises(expected): await hass.services.async_call( @@ -110,6 +110,8 @@ async def test_siren_turn_on_errors( blocking=True, ) + setattr(reolink_connect, attr, original) + async def test_siren_turn_off_errors( hass: HomeAssistant, @@ -132,3 +134,5 @@ async def test_siren_turn_off_errors( {ATTR_ENTITY_ID: entity_id}, blocking=True, ) + + reolink_connect.set_siren.reset_mock(side_effect=True) diff --git a/tests/components/reolink/test_switch.py b/tests/components/reolink/test_switch.py index 7f8d606555d..f9fb18a458f 100644 --- a/tests/components/reolink/test_switch.py +++ b/tests/components/reolink/test_switch.py @@ -138,7 +138,7 @@ async def test_switch( ) # test switch turn off - reolink_connect.set_recording.side_effect = None + reolink_connect.set_recording.reset_mock(side_effect=True) await hass.services.async_call( SWITCH_DOMAIN, SERVICE_TURN_OFF, @@ -156,6 +156,8 @@ async def test_switch( blocking=True, ) + reolink_connect.set_recording.reset_mock(side_effect=True) + async def test_host_switch( hass: HomeAssistant, @@ -165,6 +167,7 @@ async def test_host_switch( ) -> None: """Test host switch entity.""" reolink_connect.camera_name.return_value = TEST_CAM_NAME + reolink_connect.recording_enabled.return_value = True with patch("homeassistant.components.reolink.PLATFORMS", [Platform.SWITCH]): assert await hass.config_entries.async_setup(config_entry.entry_id) @@ -200,7 +203,7 @@ async def test_host_switch( ) # test switch turn off - reolink_connect.set_recording.side_effect = None + reolink_connect.set_recording.reset_mock(side_effect=True) await hass.services.async_call( SWITCH_DOMAIN, SERVICE_TURN_OFF, @@ -218,6 +221,8 @@ async def test_host_switch( blocking=True, ) + reolink_connect.set_recording.reset_mock(side_effect=True) + async def test_chime_switch( hass: HomeAssistant, @@ -262,7 +267,7 @@ async def test_chime_switch( ) # test switch turn off - test_chime.set_option.side_effect = None + test_chime.set_option.reset_mock(side_effect=True) await hass.services.async_call( SWITCH_DOMAIN, SERVICE_TURN_OFF, @@ -279,3 +284,5 @@ async def test_chime_switch( {ATTR_ENTITY_ID: entity_id}, blocking=True, ) + + test_chime.set_option.reset_mock(side_effect=True) diff --git a/tests/components/reolink/test_update.py b/tests/components/reolink/test_update.py index 3ad10a11499..a13009204d7 100644 --- a/tests/components/reolink/test_update.py +++ b/tests/components/reolink/test_update.py @@ -73,6 +73,7 @@ async def test_update_firm( ) -> None: """Test update state when update available with firmware info from reolink.com.""" reolink_connect.camera_name.return_value = TEST_CAM_NAME + reolink_connect.camera_sw_version.return_value = "v1.1.0.0.0.0000" new_firmware = NewSoftwareVersion( version_string="v3.3.0.226_23031644", download_url=TEST_DOWNLOAD_URL, @@ -129,3 +130,5 @@ async def test_update_firm( await hass.async_block_till_done() assert hass.states.get(entity_id).state == STATE_OFF + + reolink_connect.update_firmware.side_effect = None