diff --git a/tests/components/modbus/conftest.py b/tests/components/modbus/conftest.py index 86eff5e44ad..a33d0932c1d 100644 --- a/tests/components/modbus/conftest.py +++ b/tests/components/modbus/conftest.py @@ -1,4 +1,5 @@ """The tests for the Modbus sensor component.""" +from dataclasses import dataclass from datetime import timedelta import logging from unittest import mock @@ -24,6 +25,16 @@ TEST_MODBUS_NAME = "modbusTest" _LOGGER = logging.getLogger(__name__) +@dataclass +class ReadResult: + """Storage class for register read results.""" + + def __init__(self, register_words): + """Init.""" + self.registers = register_words + self.bits = register_words + + @pytest.fixture def mock_pymodbus(): """Mock pymodbus.""" @@ -59,9 +70,15 @@ async def mock_modbus(hass, caplog, request, do_config): } ] } + mock_pb = mock.MagicMock() with mock.patch( - "homeassistant.components.modbus.modbus.ModbusTcpClient", autospec=True - ) as mock_pb: + "homeassistant.components.modbus.modbus.ModbusTcpClient", return_value=mock_pb + ): + mock_pb.read_coils.return_value = ReadResult([0x00]) + read_result = ReadResult([0x00, 0x00]) + mock_pb.read_discrete_inputs.return_value = read_result + mock_pb.read_input_registers.return_value = read_result + mock_pb.read_holding_registers.return_value = read_result if request.param["testLoad"]: assert await async_setup_component(hass, DOMAIN, config) is True else: @@ -77,14 +94,11 @@ async def mock_test_state(hass, request): return request.param -# dataclass -class ReadResult: - """Storage class for register read results.""" - - def __init__(self, register_words): - """Init.""" - self.registers = register_words - self.bits = register_words +@pytest.fixture +async def mock_ha(hass): + """Load homeassistant to allow service calls.""" + assert await async_setup_component(hass, "homeassistant", {}) + await hass.async_block_till_done() async def base_test( @@ -191,21 +205,3 @@ async def base_test( # Check state entity_id = f"{entity_domain}.{device_name}" return hass.states.get(entity_id).state - - -async def prepare_service_update(hass, config): - """Run test for service write_coil.""" - - config_modbus = { - DOMAIN: { - CONF_NAME: DEFAULT_HUB, - CONF_TYPE: "tcp", - CONF_HOST: "modbusTest", - CONF_PORT: 5001, - **config, - }, - } - assert await async_setup_component(hass, DOMAIN, config_modbus) - await hass.async_block_till_done() - assert await async_setup_component(hass, "homeassistant", {}) - await hass.async_block_till_done() diff --git a/tests/components/modbus/test_binary_sensor.py b/tests/components/modbus/test_binary_sensor.py index e77fd380a22..dc9a547dc18 100644 --- a/tests/components/modbus/test_binary_sensor.py +++ b/tests/components/modbus/test_binary_sensor.py @@ -20,7 +20,7 @@ from homeassistant.const import ( ) from homeassistant.core import State -from .conftest import ReadResult, base_test, prepare_service_update +from .conftest import ReadResult, base_test SENSOR_NAME = "test_binary_sensor" ENTITY_ID = f"{SENSOR_DOMAIN}.{SENSOR_NAME}" @@ -102,33 +102,34 @@ async def test_all_binary_sensor(hass, do_type, regs, expected): assert state == expected -async def test_service_binary_sensor_update(hass, mock_pymodbus): +@pytest.mark.parametrize( + "do_config", + [ + { + CONF_BINARY_SENSORS: [ + { + CONF_NAME: SENSOR_NAME, + CONF_ADDRESS: 1234, + CONF_INPUT_TYPE: CALL_TYPE_COIL, + } + ] + }, + ], +) +async def test_service_binary_sensor_update(hass, mock_modbus, mock_ha): """Run test for service homeassistant.update_entity.""" - config = { - CONF_BINARY_SENSORS: [ - { - CONF_NAME: SENSOR_NAME, - CONF_ADDRESS: 1234, - CONF_INPUT_TYPE: CALL_TYPE_COIL, - } - ] - } - mock_pymodbus.read_coils.return_value = ReadResult([0x00]) - await prepare_service_update( - hass, - config, - ) await hass.services.async_call( "homeassistant", "update_entity", {"entity_id": ENTITY_ID}, blocking=True ) await hass.async_block_till_done() assert hass.states.get(ENTITY_ID).state == STATE_OFF - mock_pymodbus.read_coils.return_value = ReadResult([0x01]) + mock_modbus.read_coils.return_value = ReadResult([0x01]) await hass.services.async_call( "homeassistant", "update_entity", {"entity_id": ENTITY_ID}, blocking=True ) + await hass.async_block_till_done() assert hass.states.get(ENTITY_ID).state == STATE_ON diff --git a/tests/components/modbus/test_climate.py b/tests/components/modbus/test_climate.py index 97d2c32ba69..71dbb6aa8a7 100644 --- a/tests/components/modbus/test_climate.py +++ b/tests/components/modbus/test_climate.py @@ -22,7 +22,7 @@ from homeassistant.const import ( ) from homeassistant.core import State -from .conftest import ReadResult, base_test, prepare_service_update +from .conftest import ReadResult, base_test CLIMATE_NAME = "test_climate" ENTITY_ID = f"{CLIMATE_DOMAIN}.{CLIMATE_NAME}" @@ -94,25 +94,24 @@ async def test_temperature_climate(hass, regs, expected): assert state == expected -async def test_service_climate_update(hass, mock_pymodbus): +@pytest.mark.parametrize( + "do_config", + [ + { + CONF_CLIMATES: [ + { + CONF_NAME: CLIMATE_NAME, + CONF_TARGET_TEMP: 117, + CONF_ADDRESS: 117, + CONF_SLAVE: 10, + CONF_SCAN_INTERVAL: 0, + } + ] + }, + ], +) +async def test_service_climate_update(hass, mock_modbus, mock_ha): """Run test for service homeassistant.update_entity.""" - - config = { - CONF_CLIMATES: [ - { - CONF_NAME: CLIMATE_NAME, - CONF_TARGET_TEMP: 117, - CONF_ADDRESS: 117, - CONF_SLAVE: 10, - CONF_SCAN_INTERVAL: 0, - } - ] - } - mock_pymodbus.read_input_registers.return_value = ReadResult([0x00]) - await prepare_service_update( - hass, - config, - ) await hass.services.async_call( "homeassistant", "update_entity", {"entity_id": ENTITY_ID}, blocking=True ) @@ -120,34 +119,75 @@ async def test_service_climate_update(hass, mock_pymodbus): @pytest.mark.parametrize( - "data_type, temperature, result", + "temperature, result, do_config", [ - (DATA_TYPE_INT16, 35, [0x00]), - (DATA_TYPE_INT32, 36, [0x00, 0x00]), - (DATA_TYPE_FLOAT32, 37.5, [0x00, 0x00]), - (DATA_TYPE_FLOAT64, "39", [0x00, 0x00, 0x00, 0x00]), + ( + 35, + [0x00], + { + CONF_CLIMATES: [ + { + CONF_NAME: CLIMATE_NAME, + CONF_TARGET_TEMP: 117, + CONF_ADDRESS: 117, + CONF_SLAVE: 10, + CONF_DATA_TYPE: DATA_TYPE_INT16, + } + ] + }, + ), + ( + 36, + [0x00, 0x00], + { + CONF_CLIMATES: [ + { + CONF_NAME: CLIMATE_NAME, + CONF_TARGET_TEMP: 117, + CONF_ADDRESS: 117, + CONF_SLAVE: 10, + CONF_DATA_TYPE: DATA_TYPE_INT32, + } + ] + }, + ), + ( + 37.5, + [0x00, 0x00], + { + CONF_CLIMATES: [ + { + CONF_NAME: CLIMATE_NAME, + CONF_TARGET_TEMP: 117, + CONF_ADDRESS: 117, + CONF_SLAVE: 10, + CONF_DATA_TYPE: DATA_TYPE_FLOAT32, + } + ] + }, + ), + ( + "39", + [0x00, 0x00, 0x00, 0x00], + { + CONF_CLIMATES: [ + { + CONF_NAME: CLIMATE_NAME, + CONF_TARGET_TEMP: 117, + CONF_ADDRESS: 117, + CONF_SLAVE: 10, + CONF_DATA_TYPE: DATA_TYPE_FLOAT64, + } + ] + }, + ), ], ) async def test_service_climate_set_temperature( - hass, data_type, temperature, result, mock_pymodbus + hass, temperature, result, mock_modbus, mock_ha ): - """Run test for service homeassistant.update_entity.""" - config = { - CONF_CLIMATES: [ - { - CONF_NAME: CLIMATE_NAME, - CONF_TARGET_TEMP: 117, - CONF_ADDRESS: 117, - CONF_SLAVE: 10, - CONF_DATA_TYPE: data_type, - } - ] - } - mock_pymodbus.read_holding_registers.return_value = ReadResult(result) - await prepare_service_update( - hass, - config, - ) + """Test set_temperature.""" + mock_modbus.read_holding_registers.return_value = ReadResult(result) await hass.services.async_call( CLIMATE_DOMAIN, "set_temperature", diff --git a/tests/components/modbus/test_cover.py b/tests/components/modbus/test_cover.py index 8d7e7e39cf8..b1add3e3745 100644 --- a/tests/components/modbus/test_cover.py +++ b/tests/components/modbus/test_cover.py @@ -29,7 +29,7 @@ from homeassistant.const import ( ) from homeassistant.core import State -from .conftest import ReadResult, base_test, prepare_service_update +from .conftest import ReadResult, base_test COVER_NAME = "test_cover" ENTITY_ID = f"{COVER_DOMAIN}.{COVER_NAME}" @@ -158,28 +158,27 @@ async def test_register_cover(hass, regs, expected): assert state == expected -async def test_service_cover_update(hass, mock_pymodbus): +@pytest.mark.parametrize( + "do_config", + [ + { + CONF_COVERS: [ + { + CONF_NAME: COVER_NAME, + CONF_ADDRESS: 1234, + CONF_STATUS_REGISTER_TYPE: CALL_TYPE_REGISTER_HOLDING, + } + ] + }, + ], +) +async def test_service_cover_update(hass, mock_modbus, mock_ha): """Run test for service homeassistant.update_entity.""" - - config = { - CONF_COVERS: [ - { - CONF_NAME: COVER_NAME, - CONF_ADDRESS: 1234, - CONF_STATUS_REGISTER_TYPE: CALL_TYPE_REGISTER_HOLDING, - } - ] - } - mock_pymodbus.read_holding_registers.return_value = ReadResult([0x00]) - await prepare_service_update( - hass, - config, - ) await hass.services.async_call( "homeassistant", "update_entity", {"entity_id": ENTITY_ID}, blocking=True ) assert hass.states.get(ENTITY_ID).state == STATE_CLOSED - mock_pymodbus.read_holding_registers.return_value = ReadResult([0x01]) + mock_modbus.read_holding_registers.return_value = ReadResult([0x01]) await hass.services.async_call( "homeassistant", "update_entity", {"entity_id": ENTITY_ID}, blocking=True ) @@ -223,51 +222,52 @@ async def test_restore_state_cover(hass, mock_test_state, mock_modbus): assert hass.states.get(ENTITY_ID).state == test_state -async def test_service_cover_move(hass, mock_pymodbus): +@pytest.mark.parametrize( + "do_config", + [ + { + CONF_COVERS: [ + { + CONF_NAME: COVER_NAME, + CONF_ADDRESS: 1234, + CONF_STATUS_REGISTER_TYPE: CALL_TYPE_REGISTER_HOLDING, + CONF_SCAN_INTERVAL: 0, + }, + { + CONF_NAME: f"{COVER_NAME}2", + CONF_INPUT_TYPE: CALL_TYPE_COIL, + CONF_ADDRESS: 1234, + CONF_SCAN_INTERVAL: 0, + }, + ] + }, + ], +) +async def test_service_cover_move(hass, mock_modbus, mock_ha): """Run test for service homeassistant.update_entity.""" ENTITY_ID2 = f"{ENTITY_ID}2" - config = { - CONF_COVERS: [ - { - CONF_NAME: COVER_NAME, - CONF_ADDRESS: 1234, - CONF_STATUS_REGISTER_TYPE: CALL_TYPE_REGISTER_HOLDING, - CONF_SCAN_INTERVAL: 0, - }, - { - CONF_NAME: f"{COVER_NAME}2", - CONF_INPUT_TYPE: CALL_TYPE_COIL, - CONF_ADDRESS: 1234, - CONF_SCAN_INTERVAL: 0, - }, - ] - } - mock_pymodbus.read_holding_registers.return_value = ReadResult([0x01]) - await prepare_service_update( - hass, - config, - ) + mock_modbus.read_holding_registers.return_value = ReadResult([0x01]) await hass.services.async_call( "cover", "open_cover", {"entity_id": ENTITY_ID}, blocking=True ) assert hass.states.get(ENTITY_ID).state == STATE_OPEN - mock_pymodbus.read_holding_registers.return_value = ReadResult([0x00]) + mock_modbus.read_holding_registers.return_value = ReadResult([0x00]) await hass.services.async_call( "cover", "close_cover", {"entity_id": ENTITY_ID}, blocking=True ) assert hass.states.get(ENTITY_ID).state == STATE_CLOSED - mock_pymodbus.reset() - mock_pymodbus.read_holding_registers.side_effect = ModbusException("fail write_") + mock_modbus.reset() + mock_modbus.read_holding_registers.side_effect = ModbusException("fail write_") await hass.services.async_call( "cover", "close_cover", {"entity_id": ENTITY_ID}, blocking=True ) - assert mock_pymodbus.read_holding_registers.called + assert mock_modbus.read_holding_registers.called assert hass.states.get(ENTITY_ID).state == STATE_UNAVAILABLE - mock_pymodbus.read_coils.side_effect = ModbusException("fail write_") + mock_modbus.read_coils.side_effect = ModbusException("fail write_") await hass.services.async_call( "cover", "close_cover", {"entity_id": ENTITY_ID2}, blocking=True ) diff --git a/tests/components/modbus/test_fan.py b/tests/components/modbus/test_fan.py index 13714d6bd0e..e0d23ad48db 100644 --- a/tests/components/modbus/test_fan.py +++ b/tests/components/modbus/test_fan.py @@ -33,7 +33,7 @@ from homeassistant.const import ( from homeassistant.core import State from homeassistant.setup import async_setup_component -from .conftest import ReadResult, base_test, prepare_service_update +from .conftest import ReadResult, base_test FAN_NAME = "test_fan" ENTITY_ID = f"{FAN_DOMAIN}.{FAN_NAME}" @@ -277,30 +277,29 @@ async def test_fan_service_turn(hass, caplog, mock_pymodbus): assert hass.states.get(ENTITY_ID).state == STATE_UNAVAILABLE -async def test_service_fan_update(hass, mock_pymodbus): +@pytest.mark.parametrize( + "do_config", + [ + { + CONF_FANS: [ + { + CONF_NAME: FAN_NAME, + CONF_ADDRESS: 1234, + CONF_WRITE_TYPE: CALL_TYPE_COIL, + CONF_VERIFY: {}, + } + ] + }, + ], +) +async def test_service_fan_update(hass, mock_modbus, mock_ha): """Run test for service homeassistant.update_entity.""" - - config = { - CONF_FANS: [ - { - CONF_NAME: FAN_NAME, - CONF_ADDRESS: 1234, - CONF_WRITE_TYPE: CALL_TYPE_COIL, - CONF_VERIFY: {}, - } - ] - } - mock_pymodbus.read_discrete_inputs.return_value = ReadResult([0x01]) - await prepare_service_update( - hass, - config, - ) - await hass.services.async_call( - "homeassistant", "update_entity", {"entity_id": ENTITY_ID}, blocking=True - ) - assert hass.states.get(ENTITY_ID).state == STATE_ON - mock_pymodbus.read_coils.return_value = ReadResult([0x00]) await hass.services.async_call( "homeassistant", "update_entity", {"entity_id": ENTITY_ID}, blocking=True ) assert hass.states.get(ENTITY_ID).state == STATE_OFF + mock_modbus.read_coils.return_value = ReadResult([0x01]) + await hass.services.async_call( + "homeassistant", "update_entity", {"entity_id": ENTITY_ID}, blocking=True + ) + assert hass.states.get(ENTITY_ID).state == STATE_ON diff --git a/tests/components/modbus/test_light.py b/tests/components/modbus/test_light.py index c7b9b820934..3b3966cdf8a 100644 --- a/tests/components/modbus/test_light.py +++ b/tests/components/modbus/test_light.py @@ -33,7 +33,7 @@ from homeassistant.const import ( from homeassistant.core import State from homeassistant.setup import async_setup_component -from .conftest import ReadResult, base_test, prepare_service_update +from .conftest import ReadResult, base_test LIGHT_NAME = "test_light" ENTITY_ID = f"{LIGHT_DOMAIN}.{LIGHT_NAME}" @@ -277,30 +277,29 @@ async def test_light_service_turn(hass, caplog, mock_pymodbus): assert hass.states.get(ENTITY_ID).state == STATE_UNAVAILABLE -async def test_service_light_update(hass, mock_pymodbus): +@pytest.mark.parametrize( + "do_config", + [ + { + CONF_LIGHTS: [ + { + CONF_NAME: LIGHT_NAME, + CONF_ADDRESS: 1234, + CONF_WRITE_TYPE: CALL_TYPE_COIL, + CONF_VERIFY: {}, + } + ] + }, + ], +) +async def test_service_light_update(hass, mock_modbus, mock_ha): """Run test for service homeassistant.update_entity.""" - - config = { - CONF_LIGHTS: [ - { - CONF_NAME: LIGHT_NAME, - CONF_ADDRESS: 1234, - CONF_WRITE_TYPE: CALL_TYPE_COIL, - CONF_VERIFY: {}, - } - ] - } - mock_pymodbus.read_discrete_inputs.return_value = ReadResult([0x01]) - await prepare_service_update( - hass, - config, - ) - await hass.services.async_call( - "homeassistant", "update_entity", {"entity_id": ENTITY_ID}, blocking=True - ) - assert hass.states.get(ENTITY_ID).state == STATE_ON - mock_pymodbus.read_coils.return_value = ReadResult([0x00]) await hass.services.async_call( "homeassistant", "update_entity", {"entity_id": ENTITY_ID}, blocking=True ) assert hass.states.get(ENTITY_ID).state == STATE_OFF + mock_modbus.read_coils.return_value = ReadResult([0x01]) + await hass.services.async_call( + "homeassistant", "update_entity", {"entity_id": ENTITY_ID}, blocking=True + ) + assert hass.states.get(ENTITY_ID).state == STATE_ON diff --git a/tests/components/modbus/test_sensor.py b/tests/components/modbus/test_sensor.py index a5ec79d62e4..ef784c9edb6 100644 --- a/tests/components/modbus/test_sensor.py +++ b/tests/components/modbus/test_sensor.py @@ -35,7 +35,7 @@ from homeassistant.const import ( ) from homeassistant.core import State -from .conftest import ReadResult, base_test, prepare_service_update +from .conftest import ReadResult, base_test SENSOR_NAME = "test_sensor" ENTITY_ID = f"{SENSOR_DOMAIN}.{SENSOR_NAME}" @@ -599,27 +599,28 @@ async def test_restore_state_sensor(hass, mock_test_state, mock_modbus): assert hass.states.get(ENTITY_ID).state == mock_test_state[0].state -async def test_service_sensor_update(hass, mock_pymodbus): +@pytest.mark.parametrize( + "do_config", + [ + { + CONF_SENSORS: [ + { + CONF_NAME: SENSOR_NAME, + CONF_ADDRESS: 1234, + CONF_INPUT_TYPE: CALL_TYPE_REGISTER_INPUT, + } + ] + }, + ], +) +async def test_service_sensor_update(hass, mock_modbus, mock_ha): """Run test for service homeassistant.update_entity.""" - config = { - CONF_SENSORS: [ - { - CONF_NAME: SENSOR_NAME, - CONF_ADDRESS: 1234, - CONF_INPUT_TYPE: CALL_TYPE_REGISTER_INPUT, - } - ] - } - mock_pymodbus.read_input_registers.return_value = ReadResult([27]) - await prepare_service_update( - hass, - config, - ) + mock_modbus.read_input_registers.return_value = ReadResult([27]) await hass.services.async_call( "homeassistant", "update_entity", {"entity_id": ENTITY_ID}, blocking=True ) assert hass.states.get(ENTITY_ID).state == "27" - mock_pymodbus.read_input_registers.return_value = ReadResult([32]) + mock_modbus.read_input_registers.return_value = ReadResult([32]) await hass.services.async_call( "homeassistant", "update_entity", {"entity_id": ENTITY_ID}, blocking=True ) diff --git a/tests/components/modbus/test_switch.py b/tests/components/modbus/test_switch.py index c620429aad2..48c8ca9e15f 100644 --- a/tests/components/modbus/test_switch.py +++ b/tests/components/modbus/test_switch.py @@ -39,7 +39,7 @@ from homeassistant.core import State from homeassistant.setup import async_setup_component import homeassistant.util.dt as dt_util -from .conftest import ReadResult, base_test, prepare_service_update +from .conftest import ReadResult, base_test from tests.common import async_fire_time_changed @@ -291,33 +291,32 @@ async def test_switch_service_turn(hass, caplog, mock_pymodbus): assert hass.states.get(ENTITY_ID).state == STATE_UNAVAILABLE -async def test_service_switch_update(hass, mock_pymodbus): +@pytest.mark.parametrize( + "do_config", + [ + { + CONF_SWITCHES: [ + { + CONF_NAME: SWITCH_NAME, + CONF_ADDRESS: 1234, + CONF_WRITE_TYPE: CALL_TYPE_COIL, + CONF_VERIFY: {}, + } + ] + }, + ], +) +async def test_service_switch_update(hass, mock_modbus, mock_ha): """Run test for service homeassistant.update_entity.""" - - config = { - CONF_SWITCHES: [ - { - CONF_NAME: SWITCH_NAME, - CONF_ADDRESS: 1234, - CONF_WRITE_TYPE: CALL_TYPE_COIL, - CONF_VERIFY: {}, - } - ] - } - mock_pymodbus.read_discrete_inputs.return_value = ReadResult([0x01]) - await prepare_service_update( - hass, - config, - ) - await hass.services.async_call( - "homeassistant", "update_entity", {"entity_id": ENTITY_ID}, blocking=True - ) - assert hass.states.get(ENTITY_ID).state == STATE_ON - mock_pymodbus.read_coils.return_value = ReadResult([0x00]) await hass.services.async_call( "homeassistant", "update_entity", {"entity_id": ENTITY_ID}, blocking=True ) assert hass.states.get(ENTITY_ID).state == STATE_OFF + mock_modbus.read_coils.return_value = ReadResult([0x01]) + await hass.services.async_call( + "homeassistant", "update_entity", {"entity_id": ENTITY_ID}, blocking=True + ) + assert hass.states.get(ENTITY_ID).state == STATE_ON async def test_delay_switch(hass, mock_pymodbus):