diff --git a/.coveragerc b/.coveragerc index a4288b278ca..5db28077014 100644 --- a/.coveragerc +++ b/.coveragerc @@ -651,10 +651,8 @@ omit = homeassistant/components/mitemp_bt/sensor.py homeassistant/components/mjpeg/camera.py homeassistant/components/mochad/* - homeassistant/components/modbus/base_platform.py homeassistant/components/modbus/climate.py homeassistant/components/modbus/modbus.py - homeassistant/components/modbus/validators.py homeassistant/components/modem_callerid/sensor.py homeassistant/components/motion_blinds/__init__.py homeassistant/components/motion_blinds/const.py diff --git a/tests/components/modbus/test_init.py b/tests/components/modbus/test_init.py index ba99df19b4d..b4657d7ee73 100644 --- a/tests/components/modbus/test_init.py +++ b/tests/components/modbus/test_init.py @@ -155,6 +155,13 @@ async def test_number_validator(): CONF_DATA_TYPE: DATA_TYPE_INT, CONF_SWAP: CONF_SWAP_BYTE, }, + { + CONF_NAME: TEST_ENTITY_NAME, + CONF_COUNT: 2, + CONF_DATA_TYPE: DATA_TYPE_CUSTOM, + CONF_STRUCTURE: ">i", + CONF_SWAP: CONF_SWAP_BYTE, + }, ], ) async def test_ok_struct_validator(do_config): @@ -197,6 +204,13 @@ async def test_ok_struct_validator(do_config): CONF_STRUCTURE: ">f", CONF_SWAP: CONF_SWAP_WORD, }, + { + CONF_NAME: TEST_ENTITY_NAME, + CONF_COUNT: 1, + CONF_DATA_TYPE: DATA_TYPE_STRING, + CONF_STRUCTURE: ">f", + CONF_SWAP: CONF_SWAP_WORD, + }, ], ) async def test_exception_struct_validator(do_config): @@ -636,6 +650,34 @@ async def test_pymodbus_close_fail(hass, caplog, mock_pymodbus): # Close() is called as part of teardown +async def test_pymodbus_connect_fail(hass, caplog): + """Run test for failing pymodbus constructor.""" + config = { + DOMAIN: [ + { + CONF_NAME: TEST_MODBUS_NAME, + CONF_TYPE: TCP, + CONF_HOST: TEST_MODBUS_HOST, + CONF_PORT: TEST_PORT_TCP, + } + ] + } + with mock.patch( + "homeassistant.components.modbus.modbus.ModbusTcpClient", autospec=True + ) as mock_pb: + caplog.set_level(logging.ERROR) + ExceptionMessage = "test connect exception" + mock_pb.connect.side_effect = ModbusException(ExceptionMessage) + + assert await async_setup_component(hass, DOMAIN, config) is True + + +# await hass.async_block_till_done() +# await hass.async_block_till_done() +# assert mock_pb.connect.called +# assert ExceptionMessage in caplog.text + + async def test_delay(hass, mock_pymodbus): """Run test for startup delay.""" diff --git a/tests/components/modbus/test_switch.py b/tests/components/modbus/test_switch.py index c14a7169ae0..7e3c2d5f6c2 100644 --- a/tests/components/modbus/test_switch.py +++ b/tests/components/modbus/test_switch.py @@ -41,7 +41,13 @@ from homeassistant.core import State from homeassistant.setup import async_setup_component import homeassistant.util.dt as dt_util -from .conftest import TEST_ENTITY_NAME, TEST_MODBUS_HOST, TEST_PORT_TCP, ReadResult +from .conftest import ( + TEST_ENTITY_NAME, + TEST_MODBUS_HOST, + TEST_PORT_TCP, + ReadResult, + do_next_cycle, +) from tests.common import async_fire_time_changed @@ -210,6 +216,45 @@ async def test_all_switch(hass, mock_do_cycle, expected): assert hass.states.get(ENTITY_ID).state == expected +@pytest.mark.parametrize( + "do_config", + [ + { + CONF_SWITCHES: [ + { + CONF_NAME: TEST_ENTITY_NAME, + CONF_ADDRESS: 1234, + CONF_SLAVE: 1, + CONF_WRITE_TYPE: CALL_TYPE_REGISTER_HOLDING, + CONF_SCAN_INTERVAL: 10, + CONF_LAZY_ERROR: 2, + CONF_VERIFY: {}, + }, + ], + }, + ], +) +@pytest.mark.parametrize( + "register_words,do_exception,start_expect,end_expect", + [ + ( + [0x00], + True, + STATE_OFF, + STATE_UNAVAILABLE, + ), + ], +) +async def test_lazy_error_switch(hass, start_expect, end_expect, mock_do_cycle): + """Run test for given config.""" + now = mock_do_cycle + assert hass.states.get(ENTITY_ID).state == start_expect + now = await do_next_cycle(hass, now, 11) + assert hass.states.get(ENTITY_ID).state == start_expect + now = await do_next_cycle(hass, now, 11) + assert hass.states.get(ENTITY_ID).state == end_expect + + @pytest.mark.parametrize( "mock_test_state", [(State(ENTITY_ID, STATE_ON),)],