Rework mysensors test fixtures (#67331)

* Reworks mysensors test fixtures

* Fix missing autospecced methods
This commit is contained in:
Martin Hjelmare 2022-03-02 07:23:36 +01:00 committed by GitHub
parent 4ea6ca7f91
commit e9496869da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 57 additions and 31 deletions

View File

@ -4,7 +4,7 @@ from __future__ import annotations
from collections.abc import AsyncGenerator, Callable, Generator from collections.abc import AsyncGenerator, Callable, Generator
import json import json
from typing import Any from typing import Any
from unittest.mock import MagicMock, patch from unittest.mock import AsyncMock, MagicMock, patch
from mysensors import BaseSyncGateway from mysensors import BaseSyncGateway
from mysensors.persistence import MySensorsJSONDecoder from mysensors.persistence import MySensorsJSONDecoder
@ -63,33 +63,44 @@ async def serial_transport_fixture(
"""Mock a serial transport.""" """Mock a serial transport."""
with patch( with patch(
"mysensors.gateway_serial.AsyncTransport", autospec=True "mysensors.gateway_serial.AsyncTransport", autospec=True
) as transport_class, patch("mysensors.AsyncTasks", autospec=True) as tasks_class: ) as transport_class, patch("mysensors.task.OTAFirmware", autospec=True), patch(
tasks = tasks_class.return_value "mysensors.task.load_fw", autospec=True
tasks.persistence = MagicMock ), patch(
"mysensors.task.Persistence", autospec=True
) as persistence_class:
persistence = persistence_class.return_value
mock_gateway_features(tasks, transport_class, gateway_nodes) mock_gateway_features(persistence, transport_class, gateway_nodes)
yield transport_class yield transport_class
def mock_gateway_features( def mock_gateway_features(
tasks: MagicMock, transport_class: MagicMock, nodes: dict[int, Sensor] persistence: MagicMock, transport_class: MagicMock, nodes: dict[int, Sensor]
) -> None: ) -> None:
"""Mock the gateway features.""" """Mock the gateway features."""
async def mock_start_persistence() -> None: async def mock_schedule_save_sensors() -> None:
"""Load nodes from via persistence.""" """Load nodes from via persistence."""
gateway = transport_class.call_args[0][0] gateway = transport_class.call_args[0][0]
gateway.sensors.update(nodes) gateway.sensors.update(nodes)
tasks.start_persistence.side_effect = mock_start_persistence persistence.schedule_save_sensors = AsyncMock(
side_effect=mock_schedule_save_sensors
)
# For some reason autospeccing does not recognize these methods.
persistence.safe_load_sensors = MagicMock()
persistence.save_sensors = MagicMock()
async def mock_start() -> None: async def mock_connect() -> None:
"""Mock the start method.""" """Mock the start method."""
transport.connect_task = MagicMock()
gateway = transport_class.call_args[0][0] gateway = transport_class.call_args[0][0]
gateway.on_conn_made(gateway) gateway.on_conn_made(gateway)
tasks.start.side_effect = mock_start transport = transport_class.return_value
transport.connect_task = None
transport.connect.side_effect = mock_connect
@pytest.fixture(name="transport") @pytest.fixture(name="transport")
@ -98,6 +109,12 @@ def transport_fixture(serial_transport: MagicMock) -> MagicMock:
return serial_transport return serial_transport
@pytest.fixture
def transport_write(transport: MagicMock) -> MagicMock:
"""Return the transport mock that accepts string messages."""
return transport.return_value.send
@pytest.fixture(name="serial_entry") @pytest.fixture(name="serial_entry")
async def serial_entry_fixture(hass: HomeAssistant) -> MockConfigEntry: async def serial_entry_fixture(hass: HomeAssistant) -> MockConfigEntry:
"""Create a config entry for a serial gateway.""" """Create a config entry for a serial gateway."""
@ -119,16 +136,28 @@ def config_entry_fixture(serial_entry: MockConfigEntry) -> MockConfigEntry:
return serial_entry return serial_entry
@pytest.fixture @pytest.fixture(name="integration")
async def integration( async def integration_fixture(
hass: HomeAssistant, transport: MagicMock, config_entry: MockConfigEntry hass: HomeAssistant, transport: MagicMock, config_entry: MockConfigEntry
) -> AsyncGenerator[tuple[MockConfigEntry, Callable[[str], None]], None]: ) -> AsyncGenerator[MockConfigEntry, None]:
"""Set up the mysensors integration with a config entry.""" """Set up the mysensors integration with a config entry."""
device = config_entry.data[CONF_DEVICE] device = config_entry.data[CONF_DEVICE]
config: dict[str, Any] = {DOMAIN: {CONF_GATEWAYS: [{CONF_DEVICE: device}]}} config: dict[str, Any] = {DOMAIN: {CONF_GATEWAYS: [{CONF_DEVICE: device}]}}
config_entry.add_to_hass(hass) config_entry.add_to_hass(hass)
def receive_message(message_string: str) -> None: with patch("homeassistant.components.mysensors.device.UPDATE_DELAY", new=0):
await async_setup_component(hass, DOMAIN, config)
await hass.async_block_till_done()
yield config_entry
@pytest.fixture
def receive_message(
transport: MagicMock, integration: MockConfigEntry
) -> Callable[[str], None]:
"""Receive a message for the gateway."""
def receive_message_callback(message_string: str) -> None:
"""Receive a message with the transport. """Receive a message with the transport.
The message_string parameter is a string in the MySensors message format. The message_string parameter is a string in the MySensors message format.
@ -137,14 +166,13 @@ async def integration(
# node_id;child_id;command;ack;type;payload\n # node_id;child_id;command;ack;type;payload\n
gateway.logic(message_string) gateway.logic(message_string)
with patch("homeassistant.components.mysensors.device.UPDATE_DELAY", new=0): return receive_message_callback
await async_setup_component(hass, DOMAIN, config)
await hass.async_block_till_done()
yield config_entry, receive_message
@pytest.fixture(name="gateway") @pytest.fixture(name="gateway")
def gateway_fixture(transport, integration) -> BaseSyncGateway: def gateway_fixture(
transport: MagicMock, integration: MockConfigEntry
) -> BaseSyncGateway:
"""Return a setup gateway.""" """Return a setup gateway."""
return transport.call_args[0][0] return transport.call_args[0][0]

View File

@ -1,8 +1,8 @@
"""Test function in __init__.py.""" """Test function in __init__.py."""
from __future__ import annotations from __future__ import annotations
from collections.abc import Callable from collections.abc import Awaitable, Callable
from typing import Any, Awaitable from typing import Any
from unittest.mock import patch from unittest.mock import patch
from aiohttp import ClientWebSocketResponse from aiohttp import ClientWebSocketResponse
@ -359,14 +359,14 @@ async def test_import(
async def test_remove_config_entry_device( async def test_remove_config_entry_device(
hass: HomeAssistant, hass: HomeAssistant,
gps_sensor: Sensor, gps_sensor: Sensor,
integration: tuple[MockConfigEntry, Callable[[str], None]], integration: MockConfigEntry,
gateway: BaseSyncGateway, gateway: BaseSyncGateway,
hass_ws_client: Callable[[HomeAssistant], Awaitable[ClientWebSocketResponse]], hass_ws_client: Callable[[HomeAssistant], Awaitable[ClientWebSocketResponse]],
) -> None: ) -> None:
"""Test that a device can be removed ok.""" """Test that a device can be removed ok."""
entity_id = "sensor.gps_sensor_1_1" entity_id = "sensor.gps_sensor_1_1"
node_id = 1 node_id = 1
config_entry, _ = integration config_entry = integration
assert await async_setup_component(hass, "config", {}) assert await async_setup_component(hass, "config", {})
await hass.async_block_till_done() await hass.async_block_till_done()

View File

@ -29,11 +29,10 @@ from tests.common import MockConfigEntry
async def test_gps_sensor( async def test_gps_sensor(
hass: HomeAssistant, hass: HomeAssistant,
gps_sensor: Sensor, gps_sensor: Sensor,
integration: tuple[MockConfigEntry, Callable[[str], None]], receive_message: Callable[[str], None],
) -> None: ) -> None:
"""Test a gps sensor.""" """Test a gps sensor."""
entity_id = "sensor.gps_sensor_1_1" entity_id = "sensor.gps_sensor_1_1"
_, receive_message = integration
state = hass.states.get(entity_id) state = hass.states.get(entity_id)
@ -59,7 +58,7 @@ async def test_gps_sensor(
async def test_power_sensor( async def test_power_sensor(
hass: HomeAssistant, hass: HomeAssistant,
power_sensor: Sensor, power_sensor: Sensor,
integration: tuple[MockConfigEntry, Callable[[str], None]], integration: MockConfigEntry,
) -> None: ) -> None:
"""Test a power sensor.""" """Test a power sensor."""
entity_id = "sensor.power_sensor_1_1" entity_id = "sensor.power_sensor_1_1"
@ -76,7 +75,7 @@ async def test_power_sensor(
async def test_energy_sensor( async def test_energy_sensor(
hass: HomeAssistant, hass: HomeAssistant,
energy_sensor: Sensor, energy_sensor: Sensor,
integration: tuple[MockConfigEntry, Callable[[str], None]], integration: MockConfigEntry,
) -> None: ) -> None:
"""Test an energy sensor.""" """Test an energy sensor."""
entity_id = "sensor.energy_sensor_1_1" entity_id = "sensor.energy_sensor_1_1"
@ -93,7 +92,7 @@ async def test_energy_sensor(
async def test_sound_sensor( async def test_sound_sensor(
hass: HomeAssistant, hass: HomeAssistant,
sound_sensor: Sensor, sound_sensor: Sensor,
integration: tuple[MockConfigEntry, Callable[[str], None]], integration: MockConfigEntry,
) -> None: ) -> None:
"""Test a sound sensor.""" """Test a sound sensor."""
entity_id = "sensor.sound_sensor_1_1" entity_id = "sensor.sound_sensor_1_1"
@ -109,7 +108,7 @@ async def test_sound_sensor(
async def test_distance_sensor( async def test_distance_sensor(
hass: HomeAssistant, hass: HomeAssistant,
distance_sensor: Sensor, distance_sensor: Sensor,
integration: tuple[MockConfigEntry, Callable[[str], None]], integration: MockConfigEntry,
) -> None: ) -> None:
"""Test a distance sensor.""" """Test a distance sensor."""
entity_id = "sensor.distance_sensor_1_1" entity_id = "sensor.distance_sensor_1_1"
@ -129,14 +128,13 @@ async def test_distance_sensor(
async def test_temperature_sensor( async def test_temperature_sensor(
hass: HomeAssistant, hass: HomeAssistant,
temperature_sensor: Sensor, temperature_sensor: Sensor,
integration: tuple[MockConfigEntry, Callable[[str], None]], receive_message: Callable[[str], None],
unit_system: UnitSystem, unit_system: UnitSystem,
unit: str, unit: str,
) -> None: ) -> None:
"""Test a temperature sensor.""" """Test a temperature sensor."""
entity_id = "sensor.temperature_sensor_1_1" entity_id = "sensor.temperature_sensor_1_1"
hass.config.units = unit_system hass.config.units = unit_system
_, receive_message = integration
temperature = "22.0" temperature = "22.0"
message_string = f"1;1;1;0;0;{temperature}\n" message_string = f"1;1;1;0;0;{temperature}\n"