From 00c9ca64c8e1cbfe067974743805cfd4e3f5d428 Mon Sep 17 00:00:00 2001 From: Adam Mills Date: Sat, 24 Nov 2018 17:08:28 -0500 Subject: [PATCH] Async tests for mqtt switch (#18685) --- tests/components/switch/test_mqtt.py | 462 ++++++++++++++------------- 1 file changed, 241 insertions(+), 221 deletions(-) diff --git a/tests/components/switch/test_mqtt.py b/tests/components/switch/test_mqtt.py index 5cdd7d23063..4099a5b7951 100644 --- a/tests/components/switch/test_mqtt.py +++ b/tests/components/switch/test_mqtt.py @@ -1,9 +1,9 @@ """The tests for the MQTT switch platform.""" import json -import unittest -from unittest.mock import patch +from asynctest import patch +import pytest -from homeassistant.setup import setup_component, async_setup_component +from homeassistant.setup import async_setup_component from homeassistant.const import STATE_ON, STATE_OFF, STATE_UNAVAILABLE,\ ATTR_ASSUMED_STATE import homeassistant.core as ha @@ -11,279 +11,297 @@ from homeassistant.components import switch, mqtt from homeassistant.components.mqtt.discovery import async_start from tests.common import ( - mock_mqtt_component, fire_mqtt_message, get_test_home_assistant, mock_coro, - async_mock_mqtt_component, async_fire_mqtt_message, MockConfigEntry) + mock_coro, async_mock_mqtt_component, async_fire_mqtt_message, + MockConfigEntry) from tests.components.switch import common -class TestSwitchMQTT(unittest.TestCase): - """Test the MQTT switch.""" +@pytest.fixture +def mock_publish(hass): + """Initialize components.""" + yield hass.loop.run_until_complete(async_mock_mqtt_component(hass)) - def setUp(self): # pylint: disable=invalid-name - """Set up things to be run when tests are started.""" - self.hass = get_test_home_assistant() - self.mock_publish = mock_mqtt_component(self.hass) - def tearDown(self): # pylint: disable=invalid-name - """Stop everything that was started.""" - self.hass.stop() +async def test_controlling_state_via_topic(hass, mock_publish): + """Test the controlling state via topic.""" + assert await async_setup_component(hass, switch.DOMAIN, { + switch.DOMAIN: { + 'platform': 'mqtt', + 'name': 'test', + 'state_topic': 'state-topic', + 'command_topic': 'command-topic', + 'payload_on': 1, + 'payload_off': 0 + } + }) - def test_controlling_state_via_topic(self): - """Test the controlling state via topic.""" - assert setup_component(self.hass, switch.DOMAIN, { + state = hass.states.get('switch.test') + assert STATE_OFF == state.state + assert not state.attributes.get(ATTR_ASSUMED_STATE) + + async_fire_mqtt_message(hass, 'state-topic', '1') + await hass.async_block_till_done() + + state = hass.states.get('switch.test') + assert STATE_ON == state.state + + async_fire_mqtt_message(hass, 'state-topic', '0') + await hass.async_block_till_done() + await hass.async_block_till_done() + + state = hass.states.get('switch.test') + assert STATE_OFF == state.state + + +async def test_sending_mqtt_commands_and_optimistic(hass, mock_publish): + """Test the sending MQTT commands in optimistic mode.""" + fake_state = ha.State('switch.test', 'on') + + with patch('homeassistant.components.switch.mqtt.async_get_last_state', + return_value=mock_coro(fake_state)): + assert await async_setup_component(hass, switch.DOMAIN, { switch.DOMAIN: { 'platform': 'mqtt', 'name': 'test', - 'state_topic': 'state-topic', - 'command_topic': 'command-topic', - 'payload_on': 1, - 'payload_off': 0 - } - }) - - state = self.hass.states.get('switch.test') - assert STATE_OFF == state.state - assert not state.attributes.get(ATTR_ASSUMED_STATE) - - fire_mqtt_message(self.hass, 'state-topic', '1') - self.hass.block_till_done() - - state = self.hass.states.get('switch.test') - assert STATE_ON == state.state - - fire_mqtt_message(self.hass, 'state-topic', '0') - self.hass.block_till_done() - - state = self.hass.states.get('switch.test') - assert STATE_OFF == state.state - - def test_sending_mqtt_commands_and_optimistic(self): - """Test the sending MQTT commands in optimistic mode.""" - fake_state = ha.State('switch.test', 'on') - - with patch('homeassistant.components.switch.mqtt.async_get_last_state', - return_value=mock_coro(fake_state)): - assert setup_component(self.hass, switch.DOMAIN, { - switch.DOMAIN: { - 'platform': 'mqtt', - 'name': 'test', - 'command_topic': 'command-topic', - 'payload_on': 'beer on', - 'payload_off': 'beer off', - 'qos': '2' - } - }) - - state = self.hass.states.get('switch.test') - assert STATE_ON == state.state - assert state.attributes.get(ATTR_ASSUMED_STATE) - - common.turn_on(self.hass, 'switch.test') - self.hass.block_till_done() - - self.mock_publish.async_publish.assert_called_once_with( - 'command-topic', 'beer on', 2, False) - self.mock_publish.async_publish.reset_mock() - state = self.hass.states.get('switch.test') - assert STATE_ON == state.state - - common.turn_off(self.hass, 'switch.test') - self.hass.block_till_done() - - self.mock_publish.async_publish.assert_called_once_with( - 'command-topic', 'beer off', 2, False) - state = self.hass.states.get('switch.test') - assert STATE_OFF == state.state - - def test_controlling_state_via_topic_and_json_message(self): - """Test the controlling state via topic and JSON message.""" - assert setup_component(self.hass, switch.DOMAIN, { - switch.DOMAIN: { - 'platform': 'mqtt', - 'name': 'test', - 'state_topic': 'state-topic', 'command_topic': 'command-topic', 'payload_on': 'beer on', 'payload_off': 'beer off', - 'value_template': '{{ value_json.val }}' + 'qos': '2' } }) - state = self.hass.states.get('switch.test') - assert STATE_OFF == state.state + state = hass.states.get('switch.test') + assert STATE_ON == state.state + assert state.attributes.get(ATTR_ASSUMED_STATE) - fire_mqtt_message(self.hass, 'state-topic', '{"val":"beer on"}') - self.hass.block_till_done() + common.turn_on(hass, 'switch.test') + await hass.async_block_till_done() - state = self.hass.states.get('switch.test') - assert STATE_ON == state.state + mock_publish.async_publish.assert_called_once_with( + 'command-topic', 'beer on', 2, False) + mock_publish.async_publish.reset_mock() + state = hass.states.get('switch.test') + assert STATE_ON == state.state - fire_mqtt_message(self.hass, 'state-topic', '{"val":"beer off"}') - self.hass.block_till_done() + common.turn_off(hass, 'switch.test') + await hass.async_block_till_done() + await hass.async_block_till_done() - state = self.hass.states.get('switch.test') - assert STATE_OFF == state.state + mock_publish.async_publish.assert_called_once_with( + 'command-topic', 'beer off', 2, False) + state = hass.states.get('switch.test') + assert STATE_OFF == state.state - def test_controlling_availability(self): - """Test the controlling state via topic.""" - assert setup_component(self.hass, switch.DOMAIN, { - switch.DOMAIN: { - 'platform': 'mqtt', - 'name': 'test', - 'state_topic': 'state-topic', - 'command_topic': 'command-topic', - 'availability_topic': 'availability_topic', - 'payload_on': 1, - 'payload_off': 0, - 'payload_available': 1, - 'payload_not_available': 0 - } - }) - state = self.hass.states.get('switch.test') - assert STATE_UNAVAILABLE == state.state +async def test_controlling_state_via_topic_and_json_message( + hass, mock_publish): + """Test the controlling state via topic and JSON message.""" + assert await async_setup_component(hass, switch.DOMAIN, { + switch.DOMAIN: { + 'platform': 'mqtt', + 'name': 'test', + 'state_topic': 'state-topic', + 'command_topic': 'command-topic', + 'payload_on': 'beer on', + 'payload_off': 'beer off', + 'value_template': '{{ value_json.val }}' + } + }) - fire_mqtt_message(self.hass, 'availability_topic', '1') - self.hass.block_till_done() + state = hass.states.get('switch.test') + assert STATE_OFF == state.state - state = self.hass.states.get('switch.test') - assert STATE_OFF == state.state - assert not state.attributes.get(ATTR_ASSUMED_STATE) + async_fire_mqtt_message(hass, 'state-topic', '{"val":"beer on"}') + await hass.async_block_till_done() + await hass.async_block_till_done() - fire_mqtt_message(self.hass, 'availability_topic', '0') - self.hass.block_till_done() + state = hass.states.get('switch.test') + assert STATE_ON == state.state - state = self.hass.states.get('switch.test') - assert STATE_UNAVAILABLE == state.state + async_fire_mqtt_message(hass, 'state-topic', '{"val":"beer off"}') + await hass.async_block_till_done() + await hass.async_block_till_done() - fire_mqtt_message(self.hass, 'state-topic', '1') - self.hass.block_till_done() + state = hass.states.get('switch.test') + assert STATE_OFF == state.state - state = self.hass.states.get('switch.test') - assert STATE_UNAVAILABLE == state.state - fire_mqtt_message(self.hass, 'availability_topic', '1') - self.hass.block_till_done() +async def test_controlling_availability(hass, mock_publish): + """Test the controlling state via topic.""" + assert await async_setup_component(hass, switch.DOMAIN, { + switch.DOMAIN: { + 'platform': 'mqtt', + 'name': 'test', + 'state_topic': 'state-topic', + 'command_topic': 'command-topic', + 'availability_topic': 'availability_topic', + 'payload_on': 1, + 'payload_off': 0, + 'payload_available': 1, + 'payload_not_available': 0 + } + }) - state = self.hass.states.get('switch.test') - assert STATE_ON == state.state + state = hass.states.get('switch.test') + assert STATE_UNAVAILABLE == state.state - def test_default_availability_payload(self): - """Test the availability payload.""" - assert setup_component(self.hass, switch.DOMAIN, { - switch.DOMAIN: { - 'platform': 'mqtt', - 'name': 'test', - 'state_topic': 'state-topic', - 'command_topic': 'command-topic', - 'availability_topic': 'availability_topic', - 'payload_on': 1, - 'payload_off': 0 - } - }) + async_fire_mqtt_message(hass, 'availability_topic', '1') + await hass.async_block_till_done() + await hass.async_block_till_done() - state = self.hass.states.get('switch.test') - assert STATE_UNAVAILABLE == state.state + state = hass.states.get('switch.test') + assert STATE_OFF == state.state + assert not state.attributes.get(ATTR_ASSUMED_STATE) - fire_mqtt_message(self.hass, 'availability_topic', 'online') - self.hass.block_till_done() + async_fire_mqtt_message(hass, 'availability_topic', '0') + await hass.async_block_till_done() + await hass.async_block_till_done() - state = self.hass.states.get('switch.test') - assert STATE_OFF == state.state - assert not state.attributes.get(ATTR_ASSUMED_STATE) + state = hass.states.get('switch.test') + assert STATE_UNAVAILABLE == state.state - fire_mqtt_message(self.hass, 'availability_topic', 'offline') - self.hass.block_till_done() + async_fire_mqtt_message(hass, 'state-topic', '1') + await hass.async_block_till_done() + await hass.async_block_till_done() - state = self.hass.states.get('switch.test') - assert STATE_UNAVAILABLE == state.state + state = hass.states.get('switch.test') + assert STATE_UNAVAILABLE == state.state - fire_mqtt_message(self.hass, 'state-topic', '1') - self.hass.block_till_done() + async_fire_mqtt_message(hass, 'availability_topic', '1') + await hass.async_block_till_done() + await hass.async_block_till_done() - state = self.hass.states.get('switch.test') - assert STATE_UNAVAILABLE == state.state + state = hass.states.get('switch.test') + assert STATE_ON == state.state - fire_mqtt_message(self.hass, 'availability_topic', 'online') - self.hass.block_till_done() - state = self.hass.states.get('switch.test') - assert STATE_ON == state.state +async def test_default_availability_payload(hass, mock_publish): + """Test the availability payload.""" + assert await async_setup_component(hass, switch.DOMAIN, { + switch.DOMAIN: { + 'platform': 'mqtt', + 'name': 'test', + 'state_topic': 'state-topic', + 'command_topic': 'command-topic', + 'availability_topic': 'availability_topic', + 'payload_on': 1, + 'payload_off': 0 + } + }) - def test_custom_availability_payload(self): - """Test the availability payload.""" - assert setup_component(self.hass, switch.DOMAIN, { - switch.DOMAIN: { - 'platform': 'mqtt', - 'name': 'test', - 'state_topic': 'state-topic', - 'command_topic': 'command-topic', - 'availability_topic': 'availability_topic', - 'payload_on': 1, - 'payload_off': 0, - 'payload_available': 'good', - 'payload_not_available': 'nogood' - } - }) + state = hass.states.get('switch.test') + assert STATE_UNAVAILABLE == state.state - state = self.hass.states.get('switch.test') - assert STATE_UNAVAILABLE == state.state + async_fire_mqtt_message(hass, 'availability_topic', 'online') + await hass.async_block_till_done() + await hass.async_block_till_done() - fire_mqtt_message(self.hass, 'availability_topic', 'good') - self.hass.block_till_done() + state = hass.states.get('switch.test') + assert STATE_OFF == state.state + assert not state.attributes.get(ATTR_ASSUMED_STATE) - state = self.hass.states.get('switch.test') - assert STATE_OFF == state.state - assert not state.attributes.get(ATTR_ASSUMED_STATE) + async_fire_mqtt_message(hass, 'availability_topic', 'offline') + await hass.async_block_till_done() + await hass.async_block_till_done() - fire_mqtt_message(self.hass, 'availability_topic', 'nogood') - self.hass.block_till_done() + state = hass.states.get('switch.test') + assert STATE_UNAVAILABLE == state.state - state = self.hass.states.get('switch.test') - assert STATE_UNAVAILABLE == state.state + async_fire_mqtt_message(hass, 'state-topic', '1') + await hass.async_block_till_done() + await hass.async_block_till_done() - fire_mqtt_message(self.hass, 'state-topic', '1') - self.hass.block_till_done() + state = hass.states.get('switch.test') + assert STATE_UNAVAILABLE == state.state - state = self.hass.states.get('switch.test') - assert STATE_UNAVAILABLE == state.state + async_fire_mqtt_message(hass, 'availability_topic', 'online') + await hass.async_block_till_done() + await hass.async_block_till_done() - fire_mqtt_message(self.hass, 'availability_topic', 'good') - self.hass.block_till_done() + state = hass.states.get('switch.test') + assert STATE_ON == state.state - state = self.hass.states.get('switch.test') - assert STATE_ON == state.state - def test_custom_state_payload(self): - """Test the state payload.""" - assert setup_component(self.hass, switch.DOMAIN, { - switch.DOMAIN: { - 'platform': 'mqtt', - 'name': 'test', - 'state_topic': 'state-topic', - 'command_topic': 'command-topic', - 'payload_on': 1, - 'payload_off': 0, - 'state_on': "HIGH", - 'state_off': "LOW", - } - }) +async def test_custom_availability_payload(hass, mock_publish): + """Test the availability payload.""" + assert await async_setup_component(hass, switch.DOMAIN, { + switch.DOMAIN: { + 'platform': 'mqtt', + 'name': 'test', + 'state_topic': 'state-topic', + 'command_topic': 'command-topic', + 'availability_topic': 'availability_topic', + 'payload_on': 1, + 'payload_off': 0, + 'payload_available': 'good', + 'payload_not_available': 'nogood' + } + }) - state = self.hass.states.get('switch.test') - assert STATE_OFF == state.state - assert not state.attributes.get(ATTR_ASSUMED_STATE) + state = hass.states.get('switch.test') + assert STATE_UNAVAILABLE == state.state - fire_mqtt_message(self.hass, 'state-topic', 'HIGH') - self.hass.block_till_done() + async_fire_mqtt_message(hass, 'availability_topic', 'good') + await hass.async_block_till_done() - state = self.hass.states.get('switch.test') - assert STATE_ON == state.state + state = hass.states.get('switch.test') + assert STATE_OFF == state.state + assert not state.attributes.get(ATTR_ASSUMED_STATE) - fire_mqtt_message(self.hass, 'state-topic', 'LOW') - self.hass.block_till_done() + async_fire_mqtt_message(hass, 'availability_topic', 'nogood') + await hass.async_block_till_done() + await hass.async_block_till_done() - state = self.hass.states.get('switch.test') - assert STATE_OFF == state.state + state = hass.states.get('switch.test') + assert STATE_UNAVAILABLE == state.state + + async_fire_mqtt_message(hass, 'state-topic', '1') + await hass.async_block_till_done() + await hass.async_block_till_done() + + state = hass.states.get('switch.test') + assert STATE_UNAVAILABLE == state.state + + async_fire_mqtt_message(hass, 'availability_topic', 'good') + await hass.async_block_till_done() + await hass.async_block_till_done() + + state = hass.states.get('switch.test') + assert STATE_ON == state.state + + +async def test_custom_state_payload(hass, mock_publish): + """Test the state payload.""" + assert await async_setup_component(hass, switch.DOMAIN, { + switch.DOMAIN: { + 'platform': 'mqtt', + 'name': 'test', + 'state_topic': 'state-topic', + 'command_topic': 'command-topic', + 'payload_on': 1, + 'payload_off': 0, + 'state_on': "HIGH", + 'state_off': "LOW", + } + }) + + state = hass.states.get('switch.test') + assert STATE_OFF == state.state + assert not state.attributes.get(ATTR_ASSUMED_STATE) + + async_fire_mqtt_message(hass, 'state-topic', 'HIGH') + await hass.async_block_till_done() + await hass.async_block_till_done() + + state = hass.states.get('switch.test') + assert STATE_ON == state.state + + async_fire_mqtt_message(hass, 'state-topic', 'LOW') + await hass.async_block_till_done() + await hass.async_block_till_done() + + state = hass.states.get('switch.test') + assert STATE_OFF == state.state async def test_unique_id(hass): @@ -307,6 +325,7 @@ async def test_unique_id(hass): async_fire_mqtt_message(hass, 'test-topic', 'payload') await hass.async_block_till_done() + await hass.async_block_till_done() assert len(hass.states.async_entity_ids()) == 2 # all switches group is 1, unique id created is 1 @@ -326,6 +345,7 @@ async def test_discovery_removal_switch(hass, mqtt_mock, caplog): async_fire_mqtt_message(hass, 'homeassistant/switch/bla/config', data) await hass.async_block_till_done() + await hass.async_block_till_done() state = hass.states.get('switch.beer') assert state is not None