core/tests/components/numato/test_init.py

162 lines
6.0 KiB
Python
Raw Normal View History

Add numato integration (#33816) * Add support for Numato 32 port USB GPIO boards Included are a binary_sensor, sensor and switch component implementations. The binary_sensor interface pushes updates via registered callback functions, so no need to poll here. Unit tests are included to test against a Numato device mockup. * Refactor numato configuration due to PR finding * Resolve minor review findings * Bump numato-gpio requirement * Load numato platforms during domain setup According to review finding * Guard from platform setup without discovery_info According to review finding * Move numato API state into hass.data According to review finding. * Avoid side effects in numato entity constructors According to review finding * Keep only first line of numato module docstrings Removed reference to the documentation. Requested by reviewer. * Minor improvements inspired by review findings * Fix async tests Pytest fixture was returning from the yield too early executing teardown code during test execution. * Improve test coverage * Configure GPIO ports early Review finding * Move read_gpio callback to outside the loop Also continue on failed switch setup, resolve other minor review findings and correct some error messages * Bump numato-gpio requirement This fixes a crash during cleanup. When any device had a communication problem, its cleanup would raise an exception which was not handled, fell through to the caller and prevented the remaining devices from being cleaned up. * Call services directly Define local helper functions for better readability. Resolves a review finding. * Assert something in every test So not only coverage is satisfied but things are actually tested to be in the expected state. Resolves a review finding. * Clarify scope of notification tests Make unit test for hass NumatoAPI independent of Home Assistant (very basic test of notifications). Improve the regular operations test for notifications. * Test for hass.states after operating switches Resolves a review finding. * Check for wrong port directions * WIP: Split numato tests to multiple files test_hass_binary_sensor_notification still fails. * Remove pytest asyncio decorator Apears to be redundant. Resolves a review finding. * Call switch services directly. Resolves a review finding. * Remove obsolete inline pylint config Co-Authored-By: Martin Hjelmare <marhje52@gmail.com> * Improve the numato_gpio module mockup Resolves a review finding. * Remove needless explicit conversions to str Resolves review findings. * Test setup of binary_sensor callbacks * Fix test_hass_binary_sensor_notification * Add forgotten await Review finding. Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2020-04-30 12:23:30 +00:00
"""Tests for the numato integration."""
from numato_gpio import NumatoGpioError
import pytest
from homeassistant.components import numato
from homeassistant.setup import async_setup_component
from .common import NUMATO_CFG, mockup_raise, mockup_return
async def test_setup_no_devices(hass, numato_fixture, monkeypatch):
"""Test handling of an 'empty' discovery.
Platform setups are expected to return after handling errors locally
without raising.
"""
monkeypatch.setattr(numato_fixture, "discover", mockup_return)
assert await async_setup_component(hass, "numato", NUMATO_CFG)
assert len(numato_fixture.devices) == 0
async def test_fail_setup_raising_discovery(hass, numato_fixture, caplog, monkeypatch):
"""Test handling of an exception during discovery.
Setup shall return False.
"""
monkeypatch.setattr(numato_fixture, "discover", mockup_raise)
assert not await async_setup_component(hass, "numato", NUMATO_CFG)
await hass.async_block_till_done()
async def test_hass_numato_api_wrong_port_directions(hass, numato_fixture):
"""Test handling of wrong port directions.
This won't happen in the current platform implementation but would raise
in case of an introduced bug in the platforms.
"""
numato_fixture.discover()
api = numato.NumatoAPI()
api.setup_output(0, 5)
api.setup_input(0, 2)
api.setup_input(0, 6)
with pytest.raises(NumatoGpioError):
api.read_adc_input(0, 5) # adc_read from output
api.read_input(0, 6) # read from output
api.write_output(0, 2, 1) # write to input
async def test_hass_numato_api_errors(hass, numato_fixture, monkeypatch):
"""Test whether Home Assistant numato API (re-)raises errors."""
numato_fixture.discover()
monkeypatch.setattr(numato_fixture.devices[0], "setup", mockup_raise)
monkeypatch.setattr(numato_fixture.devices[0], "adc_read", mockup_raise)
monkeypatch.setattr(numato_fixture.devices[0], "read", mockup_raise)
monkeypatch.setattr(numato_fixture.devices[0], "write", mockup_raise)
api = numato.NumatoAPI()
with pytest.raises(NumatoGpioError):
api.setup_input(0, 5)
api.read_adc_input(0, 1)
api.read_input(0, 2)
api.write_output(0, 2, 1)
async def test_invalid_port_number(hass, numato_fixture, config):
"""Test validation of ADC port number type."""
sensorports_cfg = config["numato"]["devices"][0]["sensors"]["ports"]
port1_config = sensorports_cfg["1"]
sensorports_cfg["one"] = port1_config
del sensorports_cfg["1"]
assert not await async_setup_component(hass, "numato", config)
await hass.async_block_till_done()
assert not numato_fixture.devices
async def test_too_low_adc_port_number(hass, numato_fixture, config):
"""Test handling of failing component setup.
Tries setting up an ADC on a port below (0) the allowed range.
"""
sensorports_cfg = config["numato"]["devices"][0]["sensors"]["ports"]
sensorports_cfg.update({0: {"name": "toolow"}})
assert not await async_setup_component(hass, "numato", config)
assert not numato_fixture.devices
async def test_too_high_adc_port_number(hass, numato_fixture, config):
"""Test handling of failing component setup.
Tries setting up an ADC on a port above (8) the allowed range.
"""
sensorports_cfg = config["numato"]["devices"][0]["sensors"]["ports"]
sensorports_cfg.update({8: {"name": "toohigh"}})
assert not await async_setup_component(hass, "numato", config)
assert not numato_fixture.devices
async def test_invalid_adc_range_value_type(hass, numato_fixture, config):
"""Test validation of ADC range config's types.
Replaces the source range beginning by a string.
"""
sensorports_cfg = config["numato"]["devices"][0]["sensors"]["ports"]
sensorports_cfg["1"]["source_range"][0] = "zero"
assert not await async_setup_component(hass, "numato", config)
assert not numato_fixture.devices
async def test_invalid_adc_source_range_length(hass, numato_fixture, config):
"""Test validation of ADC range config's length.
Adds an element to the source range.
"""
sensorports_cfg = config["numato"]["devices"][0]["sensors"]["ports"]
sensorports_cfg["1"]["source_range"].append(42)
assert not await async_setup_component(hass, "numato", config)
assert not numato_fixture.devices
async def test_invalid_adc_source_range_order(hass, numato_fixture, config):
"""Test validation of ADC range config's order.
Sets the source range to a decreasing [2, 1].
"""
sensorports_cfg = config["numato"]["devices"][0]["sensors"]["ports"]
sensorports_cfg["1"]["source_range"] = [2, 1]
assert not await async_setup_component(hass, "numato", config)
assert not numato_fixture.devices
async def test_invalid_adc_destination_range_value_type(hass, numato_fixture, config):
"""Test validation of ADC range .
Replaces the destination range beginning by a string.
"""
sensorports_cfg = config["numato"]["devices"][0]["sensors"]["ports"]
sensorports_cfg["1"]["destination_range"][0] = "zero"
assert not await async_setup_component(hass, "numato", config)
assert not numato_fixture.devices
async def test_invalid_adc_destination_range_length(hass, numato_fixture, config):
"""Test validation of ADC range config's length.
Adds an element to the destination range.
"""
sensorports_cfg = config["numato"]["devices"][0]["sensors"]["ports"]
sensorports_cfg["1"]["destination_range"].append(42)
assert not await async_setup_component(hass, "numato", config)
assert not numato_fixture.devices
async def test_invalid_adc_destination_range_order(hass, numato_fixture, config):
"""Test validation of ADC range config's order.
Sets the destination range to a decreasing [2, 1].
"""
sensorports_cfg = config["numato"]["devices"][0]["sensors"]["ports"]
sensorports_cfg["1"]["destination_range"] = [2, 1]
assert not await async_setup_component(hass, "numato", config)
assert not numato_fixture.devices