From 8d1da7cc383ff15c580dd7626cdc21c2ef253426 Mon Sep 17 00:00:00 2001 From: Tobias Sauerwein Date: Sun, 19 Nov 2017 23:01:39 +0000 Subject: [PATCH] Add unittest for yahoo weather component. --- tests/components/weather/test_yweather.py | 186 ++++++++++++++++++++++ tests/fixtures/yahooweather.json | 138 ++++++++++++++++ 2 files changed, 324 insertions(+) create mode 100644 tests/components/weather/test_yweather.py create mode 100644 tests/fixtures/yahooweather.json diff --git a/tests/components/weather/test_yweather.py b/tests/components/weather/test_yweather.py new file mode 100644 index 00000000000..1d4dfea6f43 --- /dev/null +++ b/tests/components/weather/test_yweather.py @@ -0,0 +1,186 @@ +"""The tests for the Yahoo weather component.""" +import json + +import unittest +import requests_mock +from unittest.mock import patch, MagicMock + +#from homeassistant.components import weather +from homeassistant.components.weather import yweather +from homeassistant.components.weather import ( + ATTR_WEATHER_ATTRIBUTION, ATTR_WEATHER_HUMIDITY, ATTR_WEATHER_OZONE, + ATTR_WEATHER_PRESSURE, ATTR_WEATHER_TEMPERATURE, ATTR_WEATHER_WIND_BEARING, + ATTR_WEATHER_WIND_SPEED, ATTR_FORECAST, ATTR_FORECAST_TEMP) +from homeassistant.util.unit_system import METRIC_SYSTEM +from homeassistant.setup import setup_component + +from tests.common import get_test_home_assistant, load_fixture + + +def mock_responses(mock): + """Mock responses for Yahoo Weather.""" + base_url = 'https://query.yahooapis.com/v1/public/yql' + mock.get(base_url + + '?q=SELECT+woeid+FROM+geo.places+WHERE+text+%3D+%27%2832.87336'+ + '%2C-117.22743%29%27&format=json', + text=load_fixture('yahooweather.json')) + +def _yql_queryMock(yql): + """Mock yahoo query language query.""" + return ('{"query": {"count": 1, "created": "2017-11-17T13:40:47Z", ' + '"lang": "en-US", "results": {"place": {"woeid": "23511632"}}}}') + +def get_woeidMock(lat, lon): + """Mock get woeid Where On Earth Identifiers.""" + return '23511632' + +class YahooWeatherMock(): + """Mock class for the YahooWeather object.""" + + def __init__(self, woeid, temp_unit): + """Initialize Telnet object.""" + self.woeid = woeid + self.temp_unit = temp_unit + self._data = json.loads(load_fixture('yahooweather.json')) + + def updateWeather(self): + """Return sample values.""" + return True + + @property + def RawData(self): + """Raw Data.""" + if self.woeid == '12345': + return json.loads('[]') + return self._data + + @property + def Now(self): + """Current weather data.""" + if self.woeid == '111': + raise ValueError + return None + return self._data['query']['results']['channel']['item']['condition'] + + @property + def Atmosphere(self): + """Atmosphere weather data.""" + return self._data['query']['results']['channel']['atmosphere'] + + @property + def Wind(self): + """Wind weather data.""" + return self._data['query']['results']['channel']['wind'] + + @property + def Forecast(self): + """Forecast data 0-5 Days.""" + if self.woeid == '123123': + raise ValueError + else: + return self._data['query']['results']['channel']['item']['forecast'] + return None + + +class TestWeather(unittest.TestCase): + """Test the Yahoo weather component.""" + + DEVICES = [] + + @requests_mock.Mocker() + def add_devices(self, devices, mock): + """Mock add devices.""" + mock_responses(mock) + for device in devices: + device.update() + self.DEVICES.append(device) + + def setUp(self): + """Setup things to be run when tests are started.""" + self.hass = get_test_home_assistant() + self.hass.config.units = METRIC_SYSTEM + + def tearDown(self): + """Stop down everything that was started.""" + self.hass.stop() + + @patch('yahooweather._yql_query', new=_yql_queryMock) + @patch('yahooweather.get_woeid', new=get_woeidMock) + @patch('yahooweather.YahooWeather', new=YahooWeatherMock) + @requests_mock.Mocker() + def test_setup(self, mock): + """Test for typical weather data attributes.""" + mock_responses(mock) + self.assertTrue( + setup_component(self.hass, 'weather', { + 'weather': { + 'platform': 'yweather', + } + })) + + state = self.hass.states.get('weather.yweather') + assert state is not None + + assert state.state == 'cloudy' + + data = state.attributes + self.assertEqual(data.get(ATTR_WEATHER_TEMPERATURE), 18.0) + self.assertEqual(data.get(ATTR_WEATHER_HUMIDITY), 71) + self.assertEqual(data.get(ATTR_WEATHER_PRESSURE), 34100.95) + self.assertEqual(data.get(ATTR_WEATHER_WIND_SPEED), 6.44) + self.assertEqual(data.get(ATTR_WEATHER_WIND_BEARING), 0) + self.assertEqual(state.attributes.get('friendly_name'), 'Yweather') + + @patch('yahooweather._yql_query', new=_yql_queryMock) + @patch('yahooweather.get_woeid', new=get_woeidMock) + @patch('yahooweather.YahooWeather', new=YahooWeatherMock) + @requests_mock.Mocker() + def test_setup_no_data(self, mock): + """Test for note receiving data.""" + mock_responses(mock) + self.assertTrue( + setup_component(self.hass, 'weather', { + 'weather': { + 'platform': 'yweather', + 'woeid': '12345', + } + })) + + state = self.hass.states.get('weather.yweather') + assert state is not None + + @patch('yahooweather._yql_query', new=_yql_queryMock) + @patch('yahooweather.get_woeid', new=get_woeidMock) + @patch('yahooweather.YahooWeather', new=YahooWeatherMock) + @requests_mock.Mocker() + def test_setup_bad_data(self, mock): + """Test for bad forecast data.""" + mock_responses(mock) + self.assertTrue( + setup_component(self.hass, 'weather', { + 'weather': { + 'platform': 'yweather', + 'woeid': '123123', + } + })) + + state = self.hass.states.get('weather.yweather') + assert state is None + + @patch('yahooweather._yql_query', new=_yql_queryMock) + @patch('yahooweather.get_woeid', new=get_woeidMock) + @patch('yahooweather.YahooWeather', new=YahooWeatherMock) + @requests_mock.Mocker() + def test_setup_condition_error(self, mock): + """Test for bad forecast data.""" + mock_responses(mock) + self.assertTrue( + setup_component(self.hass, 'weather', { + 'weather': { + 'platform': 'yweather', + 'woeid': '111', + } + })) + + state = self.hass.states.get('weather.yweather') + assert state is None diff --git a/tests/fixtures/yahooweather.json b/tests/fixtures/yahooweather.json new file mode 100644 index 00000000000..f29e146873b --- /dev/null +++ b/tests/fixtures/yahooweather.json @@ -0,0 +1,138 @@ +{ + "query": { + "count": 1, + "created": "2017-11-17T13:40:47Z", + "lang": "en-US", + "results": { + "channel": { + "units": { + "distance": "km", + "pressure": "mb", + "speed": "km/h", + "temperature": "C" + }, + "title": "Yahoo! Weather - San Diego, CA, US", + "link": "http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-23511632/", + "description": "Yahoo! Weather for San Diego, CA, US", + "language": "en-us", + "lastBuildDate": "Fri, 17 Nov 2017 05:40 AM PST", + "ttl": "60", + "location": { + "city": "San Diego", + "country": "United States", + "region": " CA" + }, + "wind": { + "chill": "66", + "direction": "0", + "speed": "6.44" + }, + "atmosphere": { + "humidity": "71", + "pressure": "34100.95", + "rising": "0", + "visibility": "25.91" + }, + "astronomy": { + "sunrise": "6:21 am", + "sunset": "4:47 pm" + }, + "image": { + "title": "Yahoo! Weather", + "width": "142", + "height": "18", + "link": "http://weather.yahoo.com", + "url": "http://l.yimg.com/a/i/brand/purplelogo//uh/us/news-wea.gif" + }, + "item": { + "title": "Conditions for San Diego, CA, US at 05:00 AM PST", + "lat": "32.878101", + "long": "-117.23497", + "link": "http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-23511632/", + "pubDate": "Fri, 17 Nov 2017 05:00 AM PST", + "condition": { + "code": "26", + "date": "Fri, 17 Nov 2017 05:00 AM PST", + "temp": "18", + "text": "Cloudy" + }, + "forecast": [{ + "code": "28", + "date": "17 Nov 2017", + "day": "Fri", + "high": "23", + "low": "16", + "text": "Mostly Cloudy" + }, { + "code": "30", + "date": "18 Nov 2017", + "day": "Sat", + "high": "22", + "low": "13", + "text": "Partly Cloudy" + }, { + "code": "30", + "date": "19 Nov 2017", + "day": "Sun", + "high": "22", + "low": "12", + "text": "Partly Cloudy" + }, { + "code": "28", + "date": "20 Nov 2017", + "day": "Mon", + "high": "21", + "low": "11", + "text": "Mostly Cloudy" + }, { + "code": "28", + "date": "21 Nov 2017", + "day": "Tue", + "high": "24", + "low": "14", + "text": "Mostly Cloudy" + }, { + "code": "30", + "date": "22 Nov 2017", + "day": "Wed", + "high": "27", + "low": "15", + "text": "Partly Cloudy" + }, { + "code": "34", + "date": "23 Nov 2017", + "day": "Thu", + "high": "27", + "low": "15", + "text": "Mostly Sunny" + }, { + "code": "30", + "date": "24 Nov 2017", + "day": "Fri", + "high": "23", + "low": "16", + "text": "Partly Cloudy" + }, { + "code": "30", + "date": "25 Nov 2017", + "day": "Sat", + "high": "22", + "low": "15", + "text": "Partly Cloudy" + }, { + "code": "28", + "date": "26 Nov 2017", + "day": "Sun", + "high": "24", + "low": "13", + "text": "Mostly Cloudy" + }], + "description": "\n
\nCurrent Conditions:\n
Cloudy\n
\n
\nForecast:\n
Fri - Mostly Cloudy. High: 23Low: 16\n
Sat - Partly Cloudy. High: 22Low: 13\n
Sun - Partly Cloudy. High: 22Low: 12\n
Mon - Mostly Cloudy. High: 21Low: 11\n
Tue - Mostly Cloudy. High: 24Low: 14\n
\n
\nFull Forecast at Yahoo! Weather\n
\n
\n
\n]]>", + "guid": { + "isPermaLink": "false" + } + } + } + } + } +}