Rewrite alert test to pytest (#41102)

* Rewrite alert test to pytest

* Rewrite alert test to pytest. Add mock_notifier fixture
This commit is contained in:
Alexander Pitkin 2020-10-20 00:26:40 +03:00 committed by GitHub
parent b8417a2ce2
commit f5f4570a29
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,7 +1,8 @@
"""The tests for the Alert component.""" """The tests for the Alert component."""
# pylint: disable=protected-access # pylint: disable=protected-access
from copy import deepcopy from copy import deepcopy
import unittest
import pytest
import homeassistant.components.alert as alert import homeassistant.components.alert as alert
from homeassistant.components.alert import DOMAIN from homeassistant.components.alert import DOMAIN
@ -19,9 +20,7 @@ from homeassistant.const import (
STATE_ON, STATE_ON,
) )
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.setup import setup_component from homeassistant.setup import async_setup_component
from tests.common import get_test_home_assistant
NAME = "alert_test" NAME = "alert_test"
DONE_MESSAGE = "alert_gone" DONE_MESSAGE = "alert_gone"
@ -63,14 +62,6 @@ TEST_NOACK = [
ENTITY_ID = f"{alert.DOMAIN}.{NAME}" ENTITY_ID = f"{alert.DOMAIN}.{NAME}"
def turn_on(hass, entity_id):
"""Reset the alert.
This is a legacy helper method. Do not use it for new tests.
"""
hass.add_job(async_turn_on, hass, entity_id)
@callback @callback
def async_turn_on(hass, entity_id): def async_turn_on(hass, entity_id):
"""Async reset the alert. """Async reset the alert.
@ -81,14 +72,6 @@ def async_turn_on(hass, entity_id):
hass.async_create_task(hass.services.async_call(DOMAIN, SERVICE_TURN_ON, data)) hass.async_create_task(hass.services.async_call(DOMAIN, SERVICE_TURN_ON, data))
def turn_off(hass, entity_id):
"""Acknowledge alert.
This is a legacy helper method. Do not use it for new tests.
"""
hass.add_job(async_turn_off, hass, entity_id)
@callback @callback
def async_turn_off(hass, entity_id): def async_turn_off(hass, entity_id):
"""Async acknowledge the alert. """Async acknowledge the alert.
@ -99,14 +82,6 @@ def async_turn_off(hass, entity_id):
hass.async_create_task(hass.services.async_call(DOMAIN, SERVICE_TURN_OFF, data)) hass.async_create_task(hass.services.async_call(DOMAIN, SERVICE_TURN_OFF, data))
def toggle(hass, entity_id):
"""Toggle acknowledgment of alert.
This is a legacy helper method. Do not use it for new tests.
"""
hass.add_job(async_toggle, hass, entity_id)
@callback @callback
def async_toggle(hass, entity_id): def async_toggle(hass, entity_id):
"""Async toggle acknowledgment of alert. """Async toggle acknowledgment of alert.
@ -117,239 +92,237 @@ def async_toggle(hass, entity_id):
hass.async_create_task(hass.services.async_call(DOMAIN, SERVICE_TOGGLE, data)) hass.async_create_task(hass.services.async_call(DOMAIN, SERVICE_TOGGLE, data))
# pylint: disable=invalid-name @pytest.fixture
class TestAlert(unittest.TestCase): def mock_notifier(hass):
"""Test the alert module.""" """Mock for notifier."""
events = []
def setUp(self): @callback
"""Set up things to be run when tests are started.""" def record_event(event):
self.hass = get_test_home_assistant() """Add recorded event to set."""
self._setup_notify() events.append(event)
self.addCleanup(self.hass.stop)
def _setup_notify(self): hass.services.async_register(notify.DOMAIN, NOTIFIER, record_event)
events = []
@callback return events
def record_event(event):
"""Add recorded event to set."""
events.append(event)
self.hass.services.register(notify.DOMAIN, NOTIFIER, record_event)
return events async def test_is_on(hass):
"""Test is_on method."""
hass.states.async_set(ENTITY_ID, STATE_ON)
await hass.async_block_till_done()
assert alert.is_on(hass, ENTITY_ID)
hass.states.async_set(ENTITY_ID, STATE_OFF)
await hass.async_block_till_done()
assert not alert.is_on(hass, ENTITY_ID)
def test_is_on(self):
"""Test is_on method."""
self.hass.states.set(ENTITY_ID, STATE_ON)
self.hass.block_till_done()
assert alert.is_on(self.hass, ENTITY_ID)
self.hass.states.set(ENTITY_ID, STATE_OFF)
self.hass.block_till_done()
assert not alert.is_on(self.hass, ENTITY_ID)
def test_setup(self): async def test_setup(hass):
"""Test setup method.""" """Test setup method."""
assert setup_component(self.hass, alert.DOMAIN, TEST_CONFIG) assert await async_setup_component(hass, alert.DOMAIN, TEST_CONFIG)
assert STATE_IDLE == self.hass.states.get(ENTITY_ID).state assert STATE_IDLE == hass.states.get(ENTITY_ID).state
def test_fire(self):
"""Test the alert firing."""
assert setup_component(self.hass, alert.DOMAIN, TEST_CONFIG)
self.hass.states.set("sensor.test", STATE_ON)
self.hass.block_till_done()
assert STATE_ON == self.hass.states.get(ENTITY_ID).state
def test_silence(self): async def test_fire(hass, mock_notifier):
"""Test silencing the alert.""" """Test the alert firing."""
assert setup_component(self.hass, alert.DOMAIN, TEST_CONFIG) assert await async_setup_component(hass, alert.DOMAIN, TEST_CONFIG)
self.hass.states.set("sensor.test", STATE_ON) hass.states.async_set("sensor.test", STATE_ON)
self.hass.block_till_done() await hass.async_block_till_done()
turn_off(self.hass, ENTITY_ID) assert STATE_ON == hass.states.get(ENTITY_ID).state
self.hass.block_till_done()
assert STATE_OFF == self.hass.states.get(ENTITY_ID).state
# alert should not be silenced on next fire
self.hass.states.set("sensor.test", STATE_OFF)
self.hass.block_till_done()
assert STATE_IDLE == self.hass.states.get(ENTITY_ID).state
self.hass.states.set("sensor.test", STATE_ON)
self.hass.block_till_done()
assert STATE_ON == self.hass.states.get(ENTITY_ID).state
def test_reset(self): async def test_silence(hass, mock_notifier):
"""Test resetting the alert.""" """Test silencing the alert."""
assert setup_component(self.hass, alert.DOMAIN, TEST_CONFIG) assert await async_setup_component(hass, alert.DOMAIN, TEST_CONFIG)
self.hass.states.set("sensor.test", STATE_ON) hass.states.async_set("sensor.test", STATE_ON)
self.hass.block_till_done() await hass.async_block_till_done()
turn_off(self.hass, ENTITY_ID) async_turn_off(hass, ENTITY_ID)
self.hass.block_till_done() await hass.async_block_till_done()
assert STATE_OFF == self.hass.states.get(ENTITY_ID).state assert STATE_OFF == hass.states.get(ENTITY_ID).state
turn_on(self.hass, ENTITY_ID)
self.hass.block_till_done()
assert STATE_ON == self.hass.states.get(ENTITY_ID).state
def test_toggle(self): # alert should not be silenced on next fire
"""Test toggling alert.""" hass.states.async_set("sensor.test", STATE_OFF)
assert setup_component(self.hass, alert.DOMAIN, TEST_CONFIG) await hass.async_block_till_done()
self.hass.states.set("sensor.test", STATE_ON) assert STATE_IDLE == hass.states.get(ENTITY_ID).state
self.hass.block_till_done() hass.states.async_set("sensor.test", STATE_ON)
assert STATE_ON == self.hass.states.get(ENTITY_ID).state await hass.async_block_till_done()
toggle(self.hass, ENTITY_ID) assert STATE_ON == hass.states.get(ENTITY_ID).state
self.hass.block_till_done()
assert STATE_OFF == self.hass.states.get(ENTITY_ID).state
toggle(self.hass, ENTITY_ID)
self.hass.block_till_done()
assert STATE_ON == self.hass.states.get(ENTITY_ID).state
def test_notification_no_done_message(self):
"""Test notifications."""
events = []
config = deepcopy(TEST_CONFIG)
del config[alert.DOMAIN][NAME][alert.CONF_DONE_MESSAGE]
@callback async def test_reset(hass, mock_notifier):
def record_event(event): """Test resetting the alert."""
"""Add recorded event to set.""" assert await async_setup_component(hass, alert.DOMAIN, TEST_CONFIG)
events.append(event) hass.states.async_set("sensor.test", STATE_ON)
await hass.async_block_till_done()
async_turn_off(hass, ENTITY_ID)
await hass.async_block_till_done()
assert STATE_OFF == hass.states.get(ENTITY_ID).state
async_turn_on(hass, ENTITY_ID)
await hass.async_block_till_done()
assert STATE_ON == hass.states.get(ENTITY_ID).state
self.hass.services.register(notify.DOMAIN, NOTIFIER, record_event)
assert setup_component(self.hass, alert.DOMAIN, config) async def test_toggle(hass, mock_notifier):
assert len(events) == 0 """Test toggling alert."""
assert await async_setup_component(hass, alert.DOMAIN, TEST_CONFIG)
hass.states.async_set("sensor.test", STATE_ON)
await hass.async_block_till_done()
assert STATE_ON == hass.states.get(ENTITY_ID).state
async_toggle(hass, ENTITY_ID)
await hass.async_block_till_done()
assert STATE_OFF == hass.states.get(ENTITY_ID).state
async_toggle(hass, ENTITY_ID)
await hass.async_block_till_done()
assert STATE_ON == hass.states.get(ENTITY_ID).state
self.hass.states.set("sensor.test", STATE_ON)
self.hass.block_till_done()
assert len(events) == 1
self.hass.states.set("sensor.test", STATE_OFF) async def test_notification_no_done_message(hass):
self.hass.block_till_done() """Test notifications."""
assert len(events) == 1 events = []
config = deepcopy(TEST_CONFIG)
del config[alert.DOMAIN][NAME][alert.CONF_DONE_MESSAGE]
def test_notification(self): @callback
"""Test notifications.""" def record_event(event):
events = [] """Add recorded event to set."""
events.append(event)
@callback hass.services.async_register(notify.DOMAIN, NOTIFIER, record_event)
def record_event(event):
"""Add recorded event to set."""
events.append(event)
self.hass.services.register(notify.DOMAIN, NOTIFIER, record_event) assert await async_setup_component(hass, alert.DOMAIN, config)
assert len(events) == 0
assert setup_component(self.hass, alert.DOMAIN, TEST_CONFIG) hass.states.async_set("sensor.test", STATE_ON)
assert len(events) == 0 await hass.async_block_till_done()
assert len(events) == 1
self.hass.states.set("sensor.test", STATE_ON) hass.states.async_set("sensor.test", STATE_OFF)
self.hass.block_till_done() await hass.async_block_till_done()
assert len(events) == 1 assert len(events) == 1
self.hass.states.set("sensor.test", STATE_OFF)
self.hass.block_till_done()
assert len(events) == 2
def test_sending_non_templated_notification(self): async def test_notification(hass):
"""Test notifications.""" """Test notifications."""
events = self._setup_notify() events = []
assert setup_component(self.hass, alert.DOMAIN, TEST_CONFIG) @callback
def record_event(event):
"""Add recorded event to set."""
events.append(event)
self.hass.states.set(TEST_ENTITY, STATE_ON) hass.services.async_register(notify.DOMAIN, NOTIFIER, record_event)
self.hass.block_till_done()
self.assertEqual(1, len(events))
last_event = events[-1]
self.assertEqual(last_event.data[notify.ATTR_MESSAGE], NAME)
def test_sending_templated_notification(self): assert await async_setup_component(hass, alert.DOMAIN, TEST_CONFIG)
"""Test templated notification.""" assert len(events) == 0
events = self._setup_notify()
config = deepcopy(TEST_CONFIG) hass.states.async_set("sensor.test", STATE_ON)
config[alert.DOMAIN][NAME][alert.CONF_ALERT_MESSAGE] = TEMPLATE await hass.async_block_till_done()
assert setup_component(self.hass, alert.DOMAIN, config) assert len(events) == 1
self.hass.states.set(TEST_ENTITY, STATE_ON) hass.states.async_set("sensor.test", STATE_OFF)
self.hass.block_till_done() await hass.async_block_till_done()
self.assertEqual(1, len(events)) assert len(events) == 2
last_event = events[-1]
self.assertEqual(last_event.data[notify.ATTR_MESSAGE], TEST_ENTITY)
def test_sending_templated_done_notification(self):
"""Test templated notification."""
events = self._setup_notify()
config = deepcopy(TEST_CONFIG) async def test_sending_non_templated_notification(hass, mock_notifier):
config[alert.DOMAIN][NAME][alert.CONF_DONE_MESSAGE] = TEMPLATE """Test notifications."""
assert setup_component(self.hass, alert.DOMAIN, config) assert await async_setup_component(hass, alert.DOMAIN, TEST_CONFIG)
self.hass.states.set(TEST_ENTITY, STATE_ON) hass.states.async_set(TEST_ENTITY, STATE_ON)
self.hass.block_till_done() await hass.async_block_till_done()
self.hass.states.set(TEST_ENTITY, STATE_OFF) assert len(mock_notifier) == 1
self.hass.block_till_done() last_event = mock_notifier[-1]
self.assertEqual(2, len(events)) assert last_event.data[notify.ATTR_MESSAGE] == NAME
last_event = events[-1]
self.assertEqual(last_event.data[notify.ATTR_MESSAGE], TEST_ENTITY)
def test_sending_titled_notification(self):
"""Test notifications."""
events = self._setup_notify()
config = deepcopy(TEST_CONFIG) async def test_sending_templated_notification(hass, mock_notifier):
config[alert.DOMAIN][NAME][alert.CONF_TITLE] = TITLE """Test templated notification."""
assert setup_component(self.hass, alert.DOMAIN, config) config = deepcopy(TEST_CONFIG)
config[alert.DOMAIN][NAME][alert.CONF_ALERT_MESSAGE] = TEMPLATE
assert await async_setup_component(hass, alert.DOMAIN, config)
self.hass.states.set(TEST_ENTITY, STATE_ON) hass.states.async_set(TEST_ENTITY, STATE_ON)
self.hass.block_till_done() await hass.async_block_till_done()
self.assertEqual(1, len(events)) assert len(mock_notifier) == 1
last_event = events[-1] last_event = mock_notifier[-1]
self.assertEqual(last_event.data[notify.ATTR_TITLE], TEST_TITLE) assert last_event.data[notify.ATTR_MESSAGE] == TEST_ENTITY
def test_sending_data_notification(self):
"""Test notifications."""
events = self._setup_notify()
config = deepcopy(TEST_CONFIG) async def test_sending_templated_done_notification(hass, mock_notifier):
config[alert.DOMAIN][NAME][alert.CONF_DATA] = TEST_DATA """Test templated notification."""
assert setup_component(self.hass, alert.DOMAIN, config) config = deepcopy(TEST_CONFIG)
config[alert.DOMAIN][NAME][alert.CONF_DONE_MESSAGE] = TEMPLATE
assert await async_setup_component(hass, alert.DOMAIN, config)
self.hass.states.set(TEST_ENTITY, STATE_ON) hass.states.async_set(TEST_ENTITY, STATE_ON)
self.hass.block_till_done() await hass.async_block_till_done()
self.assertEqual(1, len(events)) hass.states.async_set(TEST_ENTITY, STATE_OFF)
last_event = events[-1] await hass.async_block_till_done()
self.assertEqual(last_event.data[notify.ATTR_DATA], TEST_DATA) assert len(mock_notifier) == 2
last_event = mock_notifier[-1]
assert last_event.data[notify.ATTR_MESSAGE] == TEST_ENTITY
def test_skipfirst(self):
"""Test skipping first notification."""
config = deepcopy(TEST_CONFIG)
config[alert.DOMAIN][NAME][alert.CONF_SKIP_FIRST] = True
events = []
@callback async def test_sending_titled_notification(hass, mock_notifier):
def record_event(event): """Test notifications."""
"""Add recorded event to set.""" config = deepcopy(TEST_CONFIG)
events.append(event) config[alert.DOMAIN][NAME][alert.CONF_TITLE] = TITLE
assert await async_setup_component(hass, alert.DOMAIN, config)
self.hass.services.register(notify.DOMAIN, NOTIFIER, record_event) hass.states.async_set(TEST_ENTITY, STATE_ON)
await hass.async_block_till_done()
assert len(mock_notifier) == 1
last_event = mock_notifier[-1]
assert last_event.data[notify.ATTR_TITLE] == TEST_TITLE
assert setup_component(self.hass, alert.DOMAIN, config)
assert len(events) == 0
self.hass.states.set("sensor.test", STATE_ON) async def test_sending_data_notification(hass, mock_notifier):
self.hass.block_till_done() """Test notifications."""
assert len(events) == 0 config = deepcopy(TEST_CONFIG)
config[alert.DOMAIN][NAME][alert.CONF_DATA] = TEST_DATA
assert await async_setup_component(hass, alert.DOMAIN, config)
def test_noack(self): hass.states.async_set(TEST_ENTITY, STATE_ON)
"""Test no ack feature.""" await hass.async_block_till_done()
entity = alert.Alert(self.hass, *TEST_NOACK) assert len(mock_notifier) == 1
self.hass.add_job(entity.begin_alerting) last_event = mock_notifier[-1]
self.hass.block_till_done() assert last_event.data[notify.ATTR_DATA] == TEST_DATA
def test_done_message_state_tracker_reset_on_cancel(self):
"""Test that the done message is reset when canceled.""" async def test_skipfirst(hass):
entity = alert.Alert(self.hass, *TEST_NOACK) """Test skipping first notification."""
entity._cancel = lambda *args: None config = deepcopy(TEST_CONFIG)
assert entity._send_done_message is False config[alert.DOMAIN][NAME][alert.CONF_SKIP_FIRST] = True
entity._send_done_message = True events = []
self.hass.add_job(entity.end_alerting)
self.hass.block_till_done() @callback
assert entity._send_done_message is False def record_event(event):
"""Add recorded event to set."""
events.append(event)
hass.services.async_register(notify.DOMAIN, NOTIFIER, record_event)
assert await async_setup_component(hass, alert.DOMAIN, config)
assert len(events) == 0
hass.states.async_set("sensor.test", STATE_ON)
await hass.async_block_till_done()
assert len(events) == 0
async def test_noack(hass):
"""Test no ack feature."""
entity = alert.Alert(hass, *TEST_NOACK)
hass.async_add_job(entity.begin_alerting)
await hass.async_block_till_done()
async def test_done_message_state_tracker_reset_on_cancel(hass):
"""Test that the done message is reset when canceled."""
entity = alert.Alert(hass, *TEST_NOACK)
entity._cancel = lambda *args: None
assert entity._send_done_message is False
entity._send_done_message = True
hass.async_add_job(entity.end_alerting)
await hass.async_block_till_done()
assert entity._send_done_message is False