1
0
mirror of https://github.com/home-assistant/core.git synced 2025-12-25 05:26:47 +00:00

Update modbus test harness (#44892)

* Update test harness to allow discovery_info testing.

This is a needed update, before the whole config is converted
to the new structure, because it allows test of both the old
and new configuration style.

The following changes have been made:
- Combine test functions into a single base_test.
- Prepare for new mock by combining the 2 common test functions into one.
- Change mock to be only modbusHub
- Do not replace whole modbus class, but only the class that
  connects to pymodbus (modbusHub). This allows test of modbus
  configurations and not only component configurations, and is needed
  when testing discovery activated platform.
- Add test of climate.
  Warning this is merely test of discovery,
  the real cover tests still needs to be added.
- Add test of cover.
  Warning this is merely test of discovery,
  the real cover tests still needs to be added.

* Update comment for old config

* Do not use hass.data, but instead patch pymodbus library.

* Add test of configuration (old/new way as available).

* Move assert to test function.

Make assert more understandable by removing it from the helper.

add base_config_test (check just calls base_test) to make it clear if
test is wanted or just controlling the config.

* use setup_component to load Modbus since it is an integration.

* Optimized flow in test helper.
This commit is contained in:
jan iversen
2021-02-14 17:40:30 +01:00
committed by GitHub
parent 9777608861
commit 855bd653b4
6 changed files with 487 additions and 207 deletions

View File

@@ -1,31 +1,25 @@
"""The tests for the Modbus sensor component."""
from datetime import timedelta
import logging
from unittest import mock
from unittest.mock import patch
import pytest
from homeassistant.components.modbus.const import (
CALL_TYPE_COIL,
CALL_TYPE_DISCRETE,
CALL_TYPE_REGISTER_INPUT,
DEFAULT_HUB,
MODBUS_DOMAIN as DOMAIN,
from homeassistant.components.modbus.const import DEFAULT_HUB, MODBUS_DOMAIN as DOMAIN
from homeassistant.const import (
CONF_HOST,
CONF_NAME,
CONF_PLATFORM,
CONF_PORT,
CONF_SCAN_INTERVAL,
CONF_TYPE,
)
from homeassistant.const import CONF_PLATFORM, CONF_SCAN_INTERVAL
from homeassistant.setup import async_setup_component
import homeassistant.util.dt as dt_util
from tests.common import async_fire_time_changed
@pytest.fixture()
def mock_hub(hass):
"""Mock hub."""
with patch("homeassistant.components.modbus.setup", return_value=True):
hub = mock.MagicMock()
hub.name = "hub"
hass.data[DOMAIN] = {DEFAULT_HUB: hub}
yield hub
_LOGGER = logging.getLogger(__name__)
class ReadResult:
@@ -37,63 +31,119 @@ class ReadResult:
self.bits = register_words
async def setup_base_test(
sensor_name,
async def base_test(
hass,
use_mock_hub,
data_array,
config_device,
device_name,
entity_domain,
scan_interval,
):
"""Run setup device for given config."""
# Full sensor configuration
config = {
entity_domain: {
CONF_PLATFORM: "modbus",
CONF_SCAN_INTERVAL: scan_interval,
**data_array,
}
}
# Initialize sensor
now = dt_util.utcnow()
with mock.patch("homeassistant.helpers.event.dt_util.utcnow", return_value=now):
assert await async_setup_component(hass, entity_domain, config)
await hass.async_block_till_done()
entity_id = f"{entity_domain}.{sensor_name}"
device = hass.states.get(entity_id)
if device is None:
pytest.fail("CONFIG failed, see output")
return entity_id, now, device
async def run_base_read_test(
entity_id,
hass,
use_mock_hub,
register_type,
array_name_discovery,
array_name_old_config,
register_words,
expected,
now,
method_discovery=False,
check_config_only=False,
config_modbus=None,
scan_interval=None,
):
"""Run test for given config."""
# Setup inputs for the sensor
read_result = ReadResult(register_words)
if register_type == CALL_TYPE_COIL:
use_mock_hub.read_coils.return_value = read_result
elif register_type == CALL_TYPE_DISCRETE:
use_mock_hub.read_discrete_inputs.return_value = read_result
elif register_type == CALL_TYPE_REGISTER_INPUT:
use_mock_hub.read_input_registers.return_value = read_result
else: # CALL_TYPE_REGISTER_HOLDING
use_mock_hub.read_holding_registers.return_value = read_result
"""Run test on device for given config."""
# Trigger update call with time_changed event
with mock.patch("homeassistant.helpers.event.dt_util.utcnow", return_value=now):
async_fire_time_changed(hass, now)
await hass.async_block_till_done()
if config_modbus is None:
config_modbus = {
DOMAIN: {
CONF_NAME: DEFAULT_HUB,
CONF_TYPE: "tcp",
CONF_HOST: "modbusTest",
CONF_PORT: 5001,
},
}
# Check state
state = hass.states.get(entity_id).state
assert state == expected
mock_sync = mock.MagicMock()
with mock.patch(
"homeassistant.components.modbus.modbus.ModbusTcpClient", return_value=mock_sync
), mock.patch(
"homeassistant.components.modbus.modbus.ModbusSerialClient",
return_value=mock_sync,
), mock.patch(
"homeassistant.components.modbus.modbus.ModbusUdpClient", return_value=mock_sync
):
# Setup inputs for the sensor
read_result = ReadResult(register_words)
mock_sync.read_coils.return_value = read_result
mock_sync.read_discrete_inputs.return_value = read_result
mock_sync.read_input_registers.return_value = read_result
mock_sync.read_holding_registers.return_value = read_result
# mock timer and add old/new config
now = dt_util.utcnow()
with mock.patch("homeassistant.helpers.event.dt_util.utcnow", return_value=now):
if method_discovery and config_device is not None:
# setup modbus which in turn does setup for the devices
config_modbus[DOMAIN].update(
{array_name_discovery: [{**config_device}]}
)
config_device = None
assert await async_setup_component(hass, DOMAIN, config_modbus)
await hass.async_block_till_done()
# setup platform old style
if config_device is not None:
config_device = {
entity_domain: {
CONF_PLATFORM: DOMAIN,
array_name_old_config: [
{
**config_device,
}
],
}
}
if scan_interval is not None:
config_device[entity_domain][CONF_SCAN_INTERVAL] = scan_interval
assert await async_setup_component(hass, entity_domain, config_device)
await hass.async_block_till_done()
assert DOMAIN in hass.data
if config_device is not None:
entity_id = f"{entity_domain}.{device_name}"
device = hass.states.get(entity_id)
if device is None:
pytest.fail("CONFIG failed, see output")
if check_config_only:
return
# Trigger update call with time_changed event
now = now + timedelta(seconds=scan_interval + 60)
with mock.patch("homeassistant.helpers.event.dt_util.utcnow", return_value=now):
async_fire_time_changed(hass, now)
await hass.async_block_till_done()
# Check state
entity_id = f"{entity_domain}.{device_name}"
return hass.states.get(entity_id).state
async def base_config_test(
hass,
config_device,
device_name,
entity_domain,
array_name_discovery,
array_name_old_config,
method_discovery=False,
config_modbus=None,
):
"""Check config of device for given config."""
await base_test(
hass,
config_device,
device_name,
entity_domain,
array_name_discovery,
array_name_old_config,
None,
None,
method_discovery=method_discovery,
check_config_only=True,
)