From 9f3701bd327539615ea8e2a658973e7391f5b4ac Mon Sep 17 00:00:00 2001 From: jan iversen Date: Thu, 8 Oct 2020 15:47:59 +0200 Subject: [PATCH] Change modbus tests to use pytest.mark.parametrize (#41486) --- .../modbus/test_modbus_binary_sensor.py | 107 ++-- tests/components/modbus/test_modbus_sensor.py | 545 +++++++----------- tests/components/modbus/test_modbus_switch.py | 37 +- 3 files changed, 282 insertions(+), 407 deletions(-) diff --git a/tests/components/modbus/test_modbus_binary_sensor.py b/tests/components/modbus/test_modbus_binary_sensor.py index 63513872e79..cb59104458e 100644 --- a/tests/components/modbus/test_modbus_binary_sensor.py +++ b/tests/components/modbus/test_modbus_binary_sensor.py @@ -2,6 +2,8 @@ from datetime import timedelta import logging +import pytest + from homeassistant.components.binary_sensor import DOMAIN as SENSOR_DOMAIN from homeassistant.components.modbus.const import ( CALL_TYPE_COIL, @@ -17,84 +19,57 @@ from .conftest import run_base_read_test, setup_base_test _LOGGER = logging.getLogger(__name__) -async def run_sensor_test(hass, use_mock_hub, register_config, value, expected): +@pytest.mark.parametrize( + "cfg,regs,expected", + [ + ( + { + CONF_INPUT_TYPE: CALL_TYPE_COIL, + }, + [0xFF], + STATE_ON, + ), + ( + { + CONF_INPUT_TYPE: CALL_TYPE_COIL, + }, + [0x00], + STATE_OFF, + ), + ( + { + CONF_INPUT_TYPE: CALL_TYPE_DISCRETE, + }, + [0xFF], + STATE_ON, + ), + ( + { + CONF_INPUT_TYPE: CALL_TYPE_DISCRETE, + }, + [0x00], + STATE_OFF, + ), + ], +) +async def test_coil_true(hass, mock_hub, cfg, regs, expected): """Run test for given config.""" sensor_name = "modbus_test_binary_sensor" scan_interval = 5 entity_id, now, device = await setup_base_test( sensor_name, hass, - use_mock_hub, - { - CONF_INPUTS: [ - dict(**{CONF_NAME: sensor_name, CONF_ADDRESS: 1234}, **register_config) - ] - }, + mock_hub, + {CONF_INPUTS: [dict(**{CONF_NAME: sensor_name, CONF_ADDRESS: 1234}, **cfg)]}, SENSOR_DOMAIN, scan_interval, ) await run_base_read_test( entity_id, hass, - use_mock_hub, - register_config.get(CONF_INPUT_TYPE), - value, + mock_hub, + cfg.get(CONF_INPUT_TYPE), + regs, expected, now + timedelta(seconds=scan_interval + 1), ) - - -async def test_coil_true(hass, mock_hub): - """Test conversion of single word register.""" - register_config = { - CONF_INPUT_TYPE: CALL_TYPE_COIL, - } - await run_sensor_test( - hass, - mock_hub, - register_config, - [0xFF], - STATE_ON, - ) - - -async def test_coil_false(hass, mock_hub): - """Test conversion of single word register.""" - register_config = { - CONF_INPUT_TYPE: CALL_TYPE_COIL, - } - await run_sensor_test( - hass, - mock_hub, - register_config, - [0x00], - STATE_OFF, - ) - - -async def test_discrete_true(hass, mock_hub): - """Test conversion of single word register.""" - register_config = { - CONF_INPUT_TYPE: CALL_TYPE_DISCRETE, - } - await run_sensor_test( - hass, - mock_hub, - register_config, - [0xFF], - expected="on", - ) - - -async def test_discrete_false(hass, mock_hub): - """Test conversion of single word register.""" - register_config = { - CONF_INPUT_TYPE: CALL_TYPE_DISCRETE, - } - await run_sensor_test( - hass, - mock_hub, - register_config, - [0x00], - expected="off", - ) diff --git a/tests/components/modbus/test_modbus_sensor.py b/tests/components/modbus/test_modbus_sensor.py index 59d845ef053..f523115bb87 100644 --- a/tests/components/modbus/test_modbus_sensor.py +++ b/tests/components/modbus/test_modbus_sensor.py @@ -2,6 +2,8 @@ from datetime import timedelta import logging +import pytest + from homeassistant.components.modbus.const import ( CALL_TYPE_REGISTER_HOLDING, CALL_TYPE_REGISTER_INPUT, @@ -27,19 +29,227 @@ from .conftest import run_base_read_test, setup_base_test _LOGGER = logging.getLogger(__name__) -async def run_sensor_test( - hass, use_mock_hub, register_config, register_words, expected -): +@pytest.mark.parametrize( + "cfg,regs,expected", + [ + ( + { + CONF_COUNT: 1, + CONF_DATA_TYPE: DATA_TYPE_INT, + CONF_SCALE: 1, + CONF_OFFSET: 0, + CONF_PRECISION: 0, + }, + [0], + "0", + ), + ( + {}, + [0x8000], + "-32768", + ), + ( + { + CONF_COUNT: 1, + CONF_DATA_TYPE: DATA_TYPE_INT, + CONF_SCALE: 1, + CONF_OFFSET: 13, + CONF_PRECISION: 0, + }, + [7], + "20", + ), + ( + { + CONF_COUNT: 1, + CONF_DATA_TYPE: DATA_TYPE_INT, + CONF_SCALE: 3, + CONF_OFFSET: 13, + CONF_PRECISION: 0, + }, + [7], + "34", + ), + ( + { + CONF_COUNT: 1, + CONF_DATA_TYPE: DATA_TYPE_UINT, + CONF_SCALE: 3, + CONF_OFFSET: 13, + CONF_PRECISION: 4, + }, + [7], + "34.0000", + ), + ( + { + CONF_COUNT: 1, + CONF_DATA_TYPE: DATA_TYPE_INT, + CONF_SCALE: 1.5, + CONF_OFFSET: 0, + CONF_PRECISION: 0, + }, + [1], + "2", + ), + ( + { + CONF_COUNT: 1, + CONF_DATA_TYPE: DATA_TYPE_INT, + CONF_SCALE: "1.5", + CONF_OFFSET: "5", + CONF_PRECISION: "1", + }, + [9], + "18.5", + ), + ( + { + CONF_COUNT: 1, + CONF_DATA_TYPE: DATA_TYPE_INT, + CONF_SCALE: 2.4, + CONF_OFFSET: 0, + CONF_PRECISION: 2, + }, + [1], + "2.40", + ), + ( + { + CONF_COUNT: 1, + CONF_DATA_TYPE: DATA_TYPE_INT, + CONF_SCALE: 1, + CONF_OFFSET: -10.3, + CONF_PRECISION: 1, + }, + [2], + "-8.3", + ), + ( + { + CONF_COUNT: 2, + CONF_DATA_TYPE: DATA_TYPE_INT, + CONF_SCALE: 1, + CONF_OFFSET: 0, + CONF_PRECISION: 0, + }, + [0x89AB, 0xCDEF], + "-1985229329", + ), + ( + { + CONF_COUNT: 2, + CONF_DATA_TYPE: DATA_TYPE_UINT, + CONF_SCALE: 1, + CONF_OFFSET: 0, + CONF_PRECISION: 0, + }, + [0x89AB, 0xCDEF], + str(0x89ABCDEF), + ), + ( + { + CONF_COUNT: 2, + CONF_DATA_TYPE: DATA_TYPE_UINT, + CONF_REVERSE_ORDER: True, + }, + [0x89AB, 0xCDEF], + str(0xCDEF89AB), + ), + ( + { + CONF_COUNT: 4, + CONF_DATA_TYPE: DATA_TYPE_UINT, + CONF_SCALE: 1, + CONF_OFFSET: 0, + CONF_PRECISION: 0, + }, + [0x89AB, 0xCDEF, 0x0123, 0x4567], + "9920249030613615975", + ), + ( + { + CONF_COUNT: 4, + CONF_DATA_TYPE: DATA_TYPE_UINT, + CONF_SCALE: 2, + CONF_OFFSET: 3, + CONF_PRECISION: 0, + }, + [0x0123, 0x4567, 0x89AB, 0xCDEF], + "163971058432973793", + ), + ( + { + CONF_COUNT: 4, + CONF_DATA_TYPE: DATA_TYPE_UINT, + CONF_SCALE: 2.0, + CONF_OFFSET: 3.0, + CONF_PRECISION: 0, + }, + [0x0123, 0x4567, 0x89AB, 0xCDEF], + "163971058432973792", + ), + ( + { + CONF_COUNT: 2, + CONF_REGISTER_TYPE: CALL_TYPE_REGISTER_INPUT, + CONF_DATA_TYPE: DATA_TYPE_UINT, + CONF_SCALE: 1, + CONF_OFFSET: 0, + CONF_PRECISION: 0, + }, + [0x89AB, 0xCDEF], + str(0x89ABCDEF), + ), + ( + { + CONF_COUNT: 2, + CONF_REGISTER_TYPE: CALL_TYPE_REGISTER_HOLDING, + CONF_DATA_TYPE: DATA_TYPE_UINT, + CONF_SCALE: 1, + CONF_OFFSET: 0, + CONF_PRECISION: 0, + }, + [0x89AB, 0xCDEF], + str(0x89ABCDEF), + ), + ( + { + CONF_COUNT: 2, + CONF_REGISTER_TYPE: CALL_TYPE_REGISTER_HOLDING, + CONF_DATA_TYPE: DATA_TYPE_FLOAT, + CONF_SCALE: 1, + CONF_OFFSET: 0, + CONF_PRECISION: 5, + }, + [16286, 1617], + "1.23457", + ), + ( + { + CONF_COUNT: 8, + CONF_REGISTER_TYPE: CALL_TYPE_REGISTER_HOLDING, + CONF_DATA_TYPE: DATA_TYPE_STRING, + CONF_SCALE: 1, + CONF_OFFSET: 0, + CONF_PRECISION: 0, + }, + [0x3037, 0x2D30, 0x352D, 0x3230, 0x3230, 0x2031, 0x343A, 0x3335], + "07-05-2020 14:35", + ), + ], +) +async def test_all_sensor(hass, mock_hub, cfg, regs, expected): """Run test for sensor.""" sensor_name = "modbus_test_sensor" scan_interval = 5 entity_id, now, device = await setup_base_test( sensor_name, hass, - use_mock_hub, + mock_hub, { CONF_REGISTERS: [ - dict(**{CONF_NAME: sensor_name, CONF_REGISTER: 1234}, **register_config) + dict(**{CONF_NAME: sensor_name, CONF_REGISTER: 1234}, **cfg) ] }, SENSOR_DOMAIN, @@ -48,328 +258,9 @@ async def run_sensor_test( await run_base_read_test( entity_id, hass, - use_mock_hub, - register_config.get(CONF_REGISTER_TYPE), - register_words, + mock_hub, + cfg.get(CONF_REGISTER_TYPE), + regs, expected, now + timedelta(seconds=scan_interval + 1), ) - - -async def test_simple_word_register(hass, mock_hub): - """Test conversion of single word register.""" - await run_sensor_test( - hass, - mock_hub, - { - CONF_COUNT: 1, - CONF_DATA_TYPE: DATA_TYPE_INT, - CONF_SCALE: 1, - CONF_OFFSET: 0, - CONF_PRECISION: 0, - }, - [0], - "0", - ) - - -async def test_optional_conf_keys(hass, mock_hub): - """Test handling of optional configuration keys.""" - await run_sensor_test( - hass, - mock_hub, - {}, - [0x8000], - "-32768", - ) - - -async def test_offset(hass, mock_hub): - """Test offset calculation.""" - await run_sensor_test( - hass, - mock_hub, - { - CONF_COUNT: 1, - CONF_DATA_TYPE: DATA_TYPE_INT, - CONF_SCALE: 1, - CONF_OFFSET: 13, - CONF_PRECISION: 0, - }, - [7], - "20", - ) - - -async def test_scale_and_offset(hass, mock_hub): - """Test handling of scale and offset.""" - await run_sensor_test( - hass, - mock_hub, - { - CONF_COUNT: 1, - CONF_DATA_TYPE: DATA_TYPE_INT, - CONF_SCALE: 3, - CONF_OFFSET: 13, - CONF_PRECISION: 0, - }, - [7], - "34", - ) - - -async def test_ints_can_have_precision(hass, mock_hub): - """Test precision can be specified event if using integer values only.""" - await run_sensor_test( - hass, - mock_hub, - { - CONF_COUNT: 1, - CONF_DATA_TYPE: DATA_TYPE_UINT, - CONF_SCALE: 3, - CONF_OFFSET: 13, - CONF_PRECISION: 4, - }, - [7], - "34.0000", - ) - - -async def test_floats_get_rounded_correctly(hass, mock_hub): - """Test that floating point values get rounded correctly.""" - await run_sensor_test( - hass, - mock_hub, - { - CONF_COUNT: 1, - CONF_DATA_TYPE: DATA_TYPE_INT, - CONF_SCALE: 1.5, - CONF_OFFSET: 0, - CONF_PRECISION: 0, - }, - [1], - "2", - ) - - -async def test_parameters_as_strings(hass, mock_hub): - """Test that scale, offset and precision can be given as strings.""" - await run_sensor_test( - hass, - mock_hub, - { - CONF_COUNT: 1, - CONF_DATA_TYPE: DATA_TYPE_INT, - CONF_SCALE: "1.5", - CONF_OFFSET: "5", - CONF_PRECISION: "1", - }, - [9], - "18.5", - ) - - -async def test_floating_point_scale(hass, mock_hub): - """Test use of floating point scale.""" - await run_sensor_test( - hass, - mock_hub, - { - CONF_COUNT: 1, - CONF_DATA_TYPE: DATA_TYPE_INT, - CONF_SCALE: 2.4, - CONF_OFFSET: 0, - CONF_PRECISION: 2, - }, - [1], - "2.40", - ) - - -async def test_floating_point_offset(hass, mock_hub): - """Test use of floating point scale.""" - await run_sensor_test( - hass, - mock_hub, - { - CONF_COUNT: 1, - CONF_DATA_TYPE: DATA_TYPE_INT, - CONF_SCALE: 1, - CONF_OFFSET: -10.3, - CONF_PRECISION: 1, - }, - [2], - "-8.3", - ) - - -async def test_signed_two_word_register(hass, mock_hub): - """Test reading of signed register with two words.""" - await run_sensor_test( - hass, - mock_hub, - { - CONF_COUNT: 2, - CONF_DATA_TYPE: DATA_TYPE_INT, - CONF_SCALE: 1, - CONF_OFFSET: 0, - CONF_PRECISION: 0, - }, - [0x89AB, 0xCDEF], - "-1985229329", - ) - - -async def test_unsigned_two_word_register(hass, mock_hub): - """Test reading of unsigned register with two words.""" - await run_sensor_test( - hass, - mock_hub, - { - CONF_COUNT: 2, - CONF_DATA_TYPE: DATA_TYPE_UINT, - CONF_SCALE: 1, - CONF_OFFSET: 0, - CONF_PRECISION: 0, - }, - [0x89AB, 0xCDEF], - str(0x89ABCDEF), - ) - - -async def test_reversed(hass, mock_hub): - """Test handling of reversed register words.""" - await run_sensor_test( - hass, - mock_hub, - { - CONF_COUNT: 2, - CONF_DATA_TYPE: DATA_TYPE_UINT, - CONF_REVERSE_ORDER: True, - }, - [0x89AB, 0xCDEF], - str(0xCDEF89AB), - ) - - -async def test_four_word_register(hass, mock_hub): - """Test reading of 64-bit register.""" - await run_sensor_test( - hass, - mock_hub, - { - CONF_COUNT: 4, - CONF_DATA_TYPE: DATA_TYPE_UINT, - CONF_SCALE: 1, - CONF_OFFSET: 0, - CONF_PRECISION: 0, - }, - [0x89AB, 0xCDEF, 0x0123, 0x4567], - "9920249030613615975", - ) - - -async def test_four_word_register_precision_is_intact_with_int_params(hass, mock_hub): - """Test that precision is not lost when doing integer arithmetic for 64-bit register.""" - await run_sensor_test( - hass, - mock_hub, - { - CONF_COUNT: 4, - CONF_DATA_TYPE: DATA_TYPE_UINT, - CONF_SCALE: 2, - CONF_OFFSET: 3, - CONF_PRECISION: 0, - }, - [0x0123, 0x4567, 0x89AB, 0xCDEF], - "163971058432973793", - ) - - -async def test_four_word_register_precision_is_lost_with_float_params(hass, mock_hub): - """Test that precision is affected when floating point conversion is done.""" - await run_sensor_test( - hass, - mock_hub, - { - CONF_COUNT: 4, - CONF_DATA_TYPE: DATA_TYPE_UINT, - CONF_SCALE: 2.0, - CONF_OFFSET: 3.0, - CONF_PRECISION: 0, - }, - [0x0123, 0x4567, 0x89AB, 0xCDEF], - "163971058432973792", - ) - - -async def test_two_word_input_register(hass, mock_hub): - """Test reaging of input register.""" - await run_sensor_test( - hass, - mock_hub, - { - CONF_COUNT: 2, - CONF_REGISTER_TYPE: CALL_TYPE_REGISTER_INPUT, - CONF_DATA_TYPE: DATA_TYPE_UINT, - CONF_SCALE: 1, - CONF_OFFSET: 0, - CONF_PRECISION: 0, - }, - [0x89AB, 0xCDEF], - str(0x89ABCDEF), - ) - - -async def test_two_word_holding_register(hass, mock_hub): - """Test reaging of holding register.""" - await run_sensor_test( - hass, - mock_hub, - { - CONF_COUNT: 2, - CONF_REGISTER_TYPE: CALL_TYPE_REGISTER_HOLDING, - CONF_DATA_TYPE: DATA_TYPE_UINT, - CONF_SCALE: 1, - CONF_OFFSET: 0, - CONF_PRECISION: 0, - }, - [0x89AB, 0xCDEF], - str(0x89ABCDEF), - ) - - -async def test_float_data_type(hass, mock_hub): - """Test floating point register data type.""" - await run_sensor_test( - hass, - mock_hub, - { - CONF_COUNT: 2, - CONF_REGISTER_TYPE: CALL_TYPE_REGISTER_HOLDING, - CONF_DATA_TYPE: DATA_TYPE_FLOAT, - CONF_SCALE: 1, - CONF_OFFSET: 0, - CONF_PRECISION: 5, - }, - [16286, 1617], - "1.23457", - ) - - -async def test_string_data_type(hass, mock_hub): - """Test byte string register data type.""" - await run_sensor_test( - hass, - mock_hub, - { - CONF_COUNT: 8, - CONF_REGISTER_TYPE: CALL_TYPE_REGISTER_HOLDING, - CONF_DATA_TYPE: DATA_TYPE_STRING, - CONF_SCALE: 1, - CONF_OFFSET: 0, - CONF_PRECISION: 0, - }, - [0x3037, 0x2D30, 0x352D, 0x3230, 0x3230, 0x2031, 0x343A, 0x3335], - "07-05-2020 14:35", - ) diff --git a/tests/components/modbus/test_modbus_switch.py b/tests/components/modbus/test_modbus_switch.py index ac1d8bd6963..9f7b6b600cd 100644 --- a/tests/components/modbus/test_modbus_switch.py +++ b/tests/components/modbus/test_modbus_switch.py @@ -2,9 +2,11 @@ from datetime import timedelta import logging +import pytest + from homeassistant.components.modbus.const import CALL_TYPE_COIL, CONF_COILS from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN -from homeassistant.const import CONF_NAME, CONF_SLAVE +from homeassistant.const import CONF_NAME, CONF_SLAVE, STATE_OFF, STATE_ON from .conftest import run_base_read_test, setup_base_test @@ -39,21 +41,28 @@ async def run_sensor_test(hass, use_mock_hub, value, expected): ) -async def test_read_coil_false(hass, mock_hub): +@pytest.mark.parametrize( + "regs,expected", + [ + ( + [0x00], + STATE_OFF, + ), + ( + [0xFF], + STATE_ON, + ), + ( + [0x01], + STATE_ON, + ), + ], +) +async def test_coil_switch(hass, mock_hub, regs, expected): """Test reading of switch coil.""" await run_sensor_test( hass, mock_hub, - [0x00], - expected="off", - ) - - -async def test_read_coil_true(hass, mock_hub): - """Test reading of switch coil.""" - await run_sensor_test( - hass, - mock_hub, - [0xFF], - expected="on", + regs, + expected, )