From b939626497d2d3a0ef66b777b21a2ed950ada842 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 4 Mar 2017 17:15:20 -0800 Subject: [PATCH] Fix tests no internet (#6411) * Fix honeywell tests without internet * Fix device tracker without internet * Fix MFI using internet during tests * Remove I/O from apns tests --- homeassistant/components/climate/honeywell.py | 1 + homeassistant/components/notify/apns.py | 46 ++-- tests/components/climate/test_honeywell.py | 3 +- tests/components/device_tracker/test_init.py | 6 +- tests/components/notify/test_apns.py | 236 ++++++++++++------ tests/components/sensor/test_mfi.py | 19 +- 6 files changed, 201 insertions(+), 110 deletions(-) diff --git a/homeassistant/components/climate/honeywell.py b/homeassistant/components/climate/honeywell.py index 7b65ed4f077..5152519459b 100644 --- a/homeassistant/components/climate/honeywell.py +++ b/homeassistant/components/climate/honeywell.py @@ -401,3 +401,4 @@ class HoneywellUSThermostat(ClimateDevice): return False self._device = devices[0] + return True diff --git a/homeassistant/components/notify/apns.py b/homeassistant/components/notify/apns.py index 09716065751..54635669766 100644 --- a/homeassistant/components/notify/apns.py +++ b/homeassistant/components/notify/apns.py @@ -126,6 +126,27 @@ class ApnsDevice(object): return not self.__eq__(other) +def _write_device(out, device): + """Write a single device to file.""" + attributes = [] + if device.name is not None: + attributes.append( + 'name: {}'.format(device.name)) + if device.tracking_device_id is not None: + attributes.append( + 'tracking_device_id: {}'.format(device.tracking_device_id)) + if device.disabled: + attributes.append('disabled: True') + + out.write(device.push_id) + out.write(": {") + if len(attributes) > 0: + separator = ", " + out.write(separator.join(attributes)) + + out.write("}\n") + + class ApnsNotificationService(BaseNotificationService): """Implement the notification service for the APNS service.""" @@ -171,32 +192,11 @@ class ApnsNotificationService(BaseNotificationService): self.device_states[entity_id] = str(to_s.state) return - @staticmethod - def write_device(out, device): - """Write a single device to file.""" - attributes = [] - if device.name is not None: - attributes.append( - 'name: {}'.format(device.name)) - if device.tracking_device_id is not None: - attributes.append( - 'tracking_device_id: {}'.format(device.tracking_device_id)) - if device.disabled: - attributes.append('disabled: True') - - out.write(device.push_id) - out.write(": {") - if len(attributes) > 0: - separator = ", " - out.write(separator.join(attributes)) - - out.write("}\n") - def write_devices(self): """Write all known devices to file.""" with open(self.yaml_path, 'w+') as out: for _, device in self.devices.items(): - ApnsNotificationService.write_device(out, device) + _write_device(out, device) def register(self, call): """Register a device to receive push messages.""" @@ -215,7 +215,7 @@ class ApnsNotificationService(BaseNotificationService): if current_device is None: self.devices[push_id] = device with open(self.yaml_path, 'a') as out: - self.write_device(out, device) + _write_device(out, device) return True if device != current_device: diff --git a/tests/components/climate/test_honeywell.py b/tests/components/climate/test_honeywell.py index a4cdda2adc4..3fcb6a1575c 100644 --- a/tests/components/climate/test_honeywell.py +++ b/tests/components/climate/test_honeywell.py @@ -436,7 +436,8 @@ class TestHoneywellUS(unittest.TestCase): self.assertFalse(self.honeywell.is_away_mode_on) self.assertEqual(self.device.hold_heat, False) - def test_retry(self): + @mock.patch('somecomfort.SomeComfort') + def test_retry(self, test_somecomfort): """Test retry connection.""" old_device = self.honeywell._device self.honeywell._retry() diff --git a/tests/components/device_tracker/test_init.py b/tests/components/device_tracker/test_init.py index c12d984d275..3d0a99ec939 100644 --- a/tests/components/device_tracker/test_init.py +++ b/tests/components/device_tracker/test_init.py @@ -24,7 +24,7 @@ from homeassistant.remote import JSONEncoder from tests.common import ( get_test_home_assistant, fire_time_changed, fire_service_discovered, - patch_yaml_files, assert_setup_component, mock_restore_cache) + patch_yaml_files, assert_setup_component, mock_restore_cache, mock_coro) from ...test_util.aiohttp import mock_aiohttp_client @@ -521,7 +521,9 @@ class TestComponentsDeviceTracker(unittest.TestCase): timedelta(seconds=0)) assert len(config) == 0 - def test_see_state(self): + @patch('homeassistant.components.device_tracker.Device' + '.set_vendor_for_mac', return_value=mock_coro()) + def test_see_state(self, mock_set_vendor): """Test device tracker see records state correctly.""" self.assertTrue(setup_component(self.hass, device_tracker.DOMAIN, TEST_PLATFORM)) diff --git a/tests/components/notify/test_apns.py b/tests/components/notify/test_apns.py index 7246aea3302..628c38ae180 100644 --- a/tests/components/notify/test_apns.py +++ b/tests/components/notify/test_apns.py @@ -1,16 +1,16 @@ """The tests for the APNS component.""" -import os +import io import unittest -from unittest.mock import patch -from unittest.mock import Mock +from unittest.mock import Mock, patch from apns2.errors import Unregistered +import yaml import homeassistant.components.notify as notify from homeassistant.bootstrap import setup_component -from homeassistant.components.notify.apns import ApnsNotificationService -from homeassistant.config import load_yaml_config_file +from homeassistant.components.notify import apns from homeassistant.core import State + from tests.common import assert_setup_component, get_test_home_assistant CONFIG = { @@ -37,6 +37,9 @@ class TestApns(unittest.TestCase): @patch('os.path.isfile', Mock(return_value=True)) @patch('os.access', Mock(return_value=True)) def _setup_notify(self): + assert isinstance(apns.load_yaml_config_file, Mock), \ + 'Found unmocked load_yaml' + with assert_setup_component(1) as handle_config: assert setup_component(self.hass, notify.DOMAIN, CONFIG) assert handle_config[notify.DOMAIN] @@ -98,69 +101,103 @@ class TestApns(unittest.TestCase): assert setup_component(self.hass, notify.DOMAIN, config) assert not handle_config[notify.DOMAIN] - def test_register_new_device(self): + @patch('homeassistant.components.notify.apns._write_device') + def test_register_new_device(self, mock_write): """Test registering a new device with a name.""" - devices_path = self.hass.config.path('test_app_apns.yaml') - with open(devices_path, 'w+') as out: - out.write('5678: {name: test device 2}\n') + yaml_file = {5678: {'name': 'test device 2'}} + + written_devices = [] + + def fake_write(_out, device): + """Fake write_device.""" + written_devices.append(device) + + mock_write.side_effect = fake_write + + with patch( + 'homeassistant.components.notify.apns.load_yaml_config_file', + Mock(return_value=yaml_file)): + self._setup_notify() - self._setup_notify() self.assertTrue(self.hass.services.call(notify.DOMAIN, 'apns_test_app', {'push_id': '1234', 'name': 'test device'}, blocking=True)) - devices = {str(key): value for (key, value) in - load_yaml_config_file(devices_path).items()} + assert len(written_devices) == 1 + assert written_devices[0].name == 'test device' - test_device_1 = devices.get('1234') - test_device_2 = devices.get('5678') - - self.assertIsNotNone(test_device_1) - self.assertIsNotNone(test_device_2) - - self.assertEqual('test device', test_device_1.get('name')) - - os.remove(devices_path) - - def test_register_device_without_name(self): + @patch('homeassistant.components.notify.apns._write_device') + def test_register_device_without_name(self, mock_write): """Test registering a without a name.""" - devices_path = self.hass.config.path('test_app_apns.yaml') - with open(devices_path, 'w+') as out: - out.write('5678: {name: test device 2}\n') + yaml_file = { + 1234: { + 'name': 'test device 1', + 'tracking_device_id': 'tracking123', + }, + 5678: { + 'name': 'test device 2', + 'tracking_device_id': 'tracking456', + }, + } + + written_devices = [] + + def fake_write(_out, device): + """Fake write_device.""" + written_devices.append(device) + + mock_write.side_effect = fake_write + + with patch( + 'homeassistant.components.notify.apns.load_yaml_config_file', + Mock(return_value=yaml_file)): + self._setup_notify() - self._setup_notify() self.assertTrue(self.hass.services.call(notify.DOMAIN, 'apns_test_app', {'push_id': '1234'}, blocking=True)) - devices = {str(key): value for (key, value) in - load_yaml_config_file(devices_path).items()} + devices = {dev.push_id: dev for dev in written_devices} test_device = devices.get('1234') self.assertIsNotNone(test_device) - self.assertIsNone(test_device.get('name')) + self.assertIsNone(test_device.name) - os.remove(devices_path) - - def test_update_existing_device(self): + @patch('homeassistant.components.notify.apns._write_device') + def test_update_existing_device(self, mock_write): """Test updating an existing device.""" - devices_path = self.hass.config.path('test_app_apns.yaml') - with open(devices_path, 'w+') as out: - out.write('1234: {name: test device 1}\n') - out.write('5678: {name: test device 2}\n') + yaml_file = { + 1234: { + 'name': 'test device 1', + }, + 5678: { + 'name': 'test device 2', + }, + } + + written_devices = [] + + def fake_write(_out, device): + """Fake write_device.""" + written_devices.append(device) + + mock_write.side_effect = fake_write + + with patch( + 'homeassistant.components.notify.apns.load_yaml_config_file', + Mock(return_value=yaml_file)): + self._setup_notify() - self._setup_notify() self.assertTrue(self.hass.services.call(notify.DOMAIN, 'apns_test_app', {'push_id': '1234', 'name': 'updated device 1'}, blocking=True)) - devices = {str(key): value for (key, value) in - load_yaml_config_file(devices_path).items()} + devices = {dev.push_id: dev for dev in written_devices} test_device_1 = devices.get('1234') test_device_2 = devices.get('5678') @@ -168,28 +205,42 @@ class TestApns(unittest.TestCase): self.assertIsNotNone(test_device_1) self.assertIsNotNone(test_device_2) - self.assertEqual('updated device 1', test_device_1.get('name')) + self.assertEqual('updated device 1', test_device_1.name) - os.remove(devices_path) - - def test_update_existing_device_with_tracking_id(self): + @patch('homeassistant.components.notify.apns._write_device') + def test_update_existing_device_with_tracking_id(self, mock_write): """Test updating an existing device that has a tracking id.""" - devices_path = self.hass.config.path('test_app_apns.yaml') - with open(devices_path, 'w+') as out: - out.write('1234: {name: test device 1, ' - 'tracking_device_id: tracking123}\n') - out.write('5678: {name: test device 2, ' - 'tracking_device_id: tracking456}\n') + yaml_file = { + 1234: { + 'name': 'test device 1', + 'tracking_device_id': 'tracking123', + }, + 5678: { + 'name': 'test device 2', + 'tracking_device_id': 'tracking456', + }, + } + + written_devices = [] + + def fake_write(_out, device): + """Fake write_device.""" + written_devices.append(device) + + mock_write.side_effect = fake_write + + with patch( + 'homeassistant.components.notify.apns.load_yaml_config_file', + Mock(return_value=yaml_file)): + self._setup_notify() - self._setup_notify() self.assertTrue(self.hass.services.call(notify.DOMAIN, 'apns_test_app', {'push_id': '1234', 'name': 'updated device 1'}, blocking=True)) - devices = {str(key): value for (key, value) in - load_yaml_config_file(devices_path).items()} + devices = {dev.push_id: dev for dev in written_devices} test_device_1 = devices.get('1234') test_device_2 = devices.get('5678') @@ -198,22 +249,21 @@ class TestApns(unittest.TestCase): self.assertIsNotNone(test_device_2) self.assertEqual('tracking123', - test_device_1.get('tracking_device_id')) + test_device_1.tracking_device_id) self.assertEqual('tracking456', - test_device_2.get('tracking_device_id')) - - os.remove(devices_path) + test_device_2.tracking_device_id) @patch('apns2.client.APNsClient') def test_send(self, mock_client): """Test updating an existing device.""" send = mock_client.return_value.send_notification - devices_path = self.hass.config.path('test_app_apns.yaml') - with open(devices_path, 'w+') as out: - out.write('1234: {name: test device 1}\n') + yaml_file = {1234: {'name': 'test device 1'}} - self._setup_notify() + with patch( + 'homeassistant.components.notify.apns.load_yaml_config_file', + Mock(return_value=yaml_file)): + self._setup_notify() self.assertTrue(self.hass.services.call( 'notify', 'test_app', @@ -240,11 +290,15 @@ class TestApns(unittest.TestCase): """Test updating an existing device.""" send = mock_client.return_value.send_notification - devices_path = self.hass.config.path('test_app_apns.yaml') - with open(devices_path, 'w+') as out: - out.write('1234: {name: test device 1, disabled: True}\n') + yaml_file = {1234: { + 'name': 'test device 1', + 'disabled': True, + }} - self._setup_notify() + with patch( + 'homeassistant.components.notify.apns.load_yaml_config_file', + Mock(return_value=yaml_file)): + self._setup_notify() self.assertTrue(self.hass.services.call( 'notify', 'test_app', @@ -268,7 +322,7 @@ class TestApns(unittest.TestCase): out.write('5678: {name: test device 2, ' 'tracking_device_id: tracking456}\n') - notify_service = ApnsNotificationService( + notify_service = apns.ApnsNotificationService( self.hass, 'test_app', 'testapp.appname', @@ -295,26 +349,58 @@ class TestApns(unittest.TestCase): self.assertEqual('Hello', payload.alert) @patch('apns2.client.APNsClient') - def test_disable_when_unregistered(self, mock_client): + @patch('homeassistant.components.notify.apns._write_device') + def test_disable_when_unregistered(self, mock_write, mock_client): """Test disabling a device when it is unregistered.""" send = mock_client.return_value.send_notification send.side_effect = Unregistered() - devices_path = self.hass.config.path('test_app_apns.yaml') - with open(devices_path, 'w+') as out: - out.write('1234: {name: test device 1}\n') + yaml_file = { + 1234: { + 'name': 'test device 1', + 'tracking_device_id': 'tracking123', + }, + 5678: { + 'name': 'test device 2', + 'tracking_device_id': 'tracking456', + }, + } - self._setup_notify() + written_devices = [] + + def fake_write(_out, device): + """Fake write_device.""" + written_devices.append(device) + + mock_write.side_effect = fake_write + + with patch( + 'homeassistant.components.notify.apns.load_yaml_config_file', + Mock(return_value=yaml_file)): + self._setup_notify() self.assertTrue(self.hass.services.call('notify', 'test_app', {'message': 'Hello'}, blocking=True)) - devices = {str(key): value for (key, value) in - load_yaml_config_file(devices_path).items()} + devices = {dev.push_id: dev for dev in written_devices} test_device_1 = devices.get('1234') self.assertIsNotNone(test_device_1) - self.assertEqual(True, test_device_1.get('disabled')) + self.assertEqual(True, test_device_1.disabled) - os.remove(devices_path) + +def test_write_device(): + """Test writing device.""" + out = io.StringIO() + device = apns.ApnsDevice('123', 'name', 'track_id', True) + + apns._write_device(out, device) + data = yaml.load(out.getvalue()) + assert data == { + 123: { + 'name': 'name', + 'tracking_device_id': 'track_id', + 'disabled': True + }, + } diff --git a/tests/components/sensor/test_mfi.py b/tests/components/sensor/test_mfi.py index 82577a5b2a0..a55250c8872 100644 --- a/tests/components/sensor/test_mfi.py +++ b/tests/components/sensor/test_mfi.py @@ -38,29 +38,31 @@ class TestMfiSensorSetup(unittest.TestCase): """Stop everything that was started.""" self.hass.stop() - def test_setup_missing_config(self): + @mock.patch('mficlient.client.MFiClient') + def test_setup_missing_config(self, mock_client): """Test setup with missing configuration.""" config = { 'sensor': { 'platform': 'mfi', } } - self.assertFalse(self.PLATFORM.setup_platform(self.hass, config, None)) + assert setup_component(self.hass, 'sensor', config) + assert not mock_client.called - @mock.patch('mficlient.client') + @mock.patch('mficlient.client.MFiClient') def test_setup_failed_login(self, mock_client): """Test setup with login failure.""" - mock_client.FailedToLogin = Exception() - mock_client.MFiClient.side_effect = mock_client.FailedToLogin + from mficlient.client import FailedToLogin + + mock_client.side_effect = FailedToLogin self.assertFalse( self.PLATFORM.setup_platform( self.hass, dict(self.GOOD_CONFIG), None)) - @mock.patch('mficlient.client') + @mock.patch('mficlient.client.MFiClient') def test_setup_failed_connect(self, mock_client): """Test setup with conection failure.""" - mock_client.FailedToLogin = Exception() - mock_client.MFiClient.side_effect = requests.exceptions.ConnectionError + mock_client.side_effect = requests.exceptions.ConnectionError self.assertFalse( self.PLATFORM.setup_platform( self.hass, dict(self.GOOD_CONFIG), None)) @@ -116,7 +118,6 @@ class TestMfiSensorSetup(unittest.TestCase): ports = {i: mock.MagicMock(model=model) for i, model in enumerate(mfi.SENSOR_MODELS)} ports['bad'] = mock.MagicMock(model='notasensor') - print(ports['bad'].model) mock_client.return_value.get_devices.return_value = \ [mock.MagicMock(ports=ports)] assert setup_component(self.hass, sensor.DOMAIN, self.GOOD_CONFIG)