-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
220 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
--- | ||
name: "Python testing" | ||
|
||
on: | ||
push: | ||
branches: | ||
- main | ||
pull_request: | ||
|
||
jobs: | ||
tests: | ||
name: "Test package" | ||
runs-on: ubuntu-latest | ||
strategy: | ||
max-parallel: 3 | ||
matrix: | ||
python-version: ['3.9', '3.10'] | ||
steps: | ||
- name: "Checkout code" | ||
uses: actions/checkout@v3 | ||
|
||
- name: Set up Python ${{ matrix.python-version }} | ||
uses: actions/setup-python@v4 | ||
with: | ||
python-version: ${{ matrix.python-version }} | ||
|
||
- name: "Cache pip" | ||
uses: actions/cache@v3 | ||
with: | ||
# This path is specific to Ubuntu | ||
path: ~/.cache/pip | ||
# Look to see if there is a cache hit for the corresponding requirements file | ||
key: ${{ runner.os }}-pip-${{ hashFiles('requirements*.txt') }} | ||
restore-keys: | | ||
${{ runner.os }}-pip- | ||
${{ runner.os }}- | ||
- name: "Install dependencies" | ||
run: | | ||
python -m pip install --upgrade pip | ||
# Prefer requirements-test.txt | ||
if [ -f requirements-test.txt ]; then | ||
bin/install_requirements requirements-test.txt "${{ secrets.ADMIN_GITHUB_TOKEN }}" | ||
elif [ -f requirements-dev.txt ]; then | ||
bin/install_requirements requirements-dev.txt "${{ secrets.ADMIN_GITHUB_TOKEN }}" | ||
elif [ -f requirements.txt ]; then | ||
bin/install_requirements requirements.txt "${{ secrets.ADMIN_GITHUB_TOKEN }}" | ||
fi | ||
pip install pytest-xdist | ||
if [ -d custom_components ]; then | ||
echo '"""Stub."""' >custom_components/__init__.py | ||
fi | ||
- name: "Run tests with pytest" | ||
if: matrix.python-version != '3.9' | ||
run: | | ||
pytest --basetemp=$RUNNER_TEMP --durations=10 -n auto --dist=loadfile -qq -o console_output_style=count -p no:sugar --asyncio-mode=auto | ||
./bin/check_dirty |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
"""Tests for integration.""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
# pylint: disable=protected-access,redefined-outer-name | ||
"""Global fixtures for integration.""" | ||
# Fixtures allow you to replace functions with a Mock object. You can perform | ||
# many options via the Mock to reflect a particular behavior from the original | ||
# function that you want to see without going through the function's actual logic. | ||
# Fixtures can either be passed into tests as parameters, or if autouse=True, they | ||
# will automatically be used across all tests. | ||
# | ||
# Fixtures that are defined in conftest.py are available across all tests. You can also | ||
# define fixtures within a particular test file to scope them locally. | ||
# | ||
# pytest_homeassistant_custom_component provides some fixtures that are provided by | ||
# Home Assistant core. You can find those fixture definitions here: | ||
# https://github.com/MatthewFlamm/pytest-homeassistant-custom-component/blob/master/pytest_homeassistant_custom_component/common.py | ||
# | ||
# See here for more info: https://docs.pytest.org/en/latest/fixture.html (note that | ||
# pytest includes fixtures OOB which you can use as defined on this page) | ||
from unittest.mock import Mock, patch | ||
|
||
import pytest | ||
|
||
from custom_components.dwd_weather.connector import DWDWeatherData | ||
from custom_components.dwd_weather.sensor import DWDWeatherForecastSensor | ||
|
||
pytest_plugins = "pytest_homeassistant_custom_component" # pylint: disable=invalid-name | ||
|
||
|
||
# This fixture enables loading custom integrations in all tests. | ||
# Remove to enable selective use of this fixture | ||
@pytest.fixture(autouse=True) | ||
def auto_enable_custom_integrations(enable_custom_integrations): | ||
"""Automatically enable loading custom integrations in all tests.""" | ||
yield | ||
|
||
|
||
# This fixture is used to prevent HomeAssistant from attempting to create and dismiss persistent | ||
# notifications. These calls would fail without this fixture since the persistent_notification | ||
# integration is never loaded during a test. | ||
@pytest.fixture(name="skip_notifications", autouse=True) | ||
def skip_notifications_fixture(): | ||
"""Skip notification calls.""" | ||
with patch("homeassistant.components.persistent_notification.async_create"), patch( | ||
"homeassistant.components.persistent_notification.async_dismiss" | ||
): | ||
yield | ||
|
||
|
||
# This fixture, when used, will result in calls to async_get_data to return None. To have the call | ||
# return a value, we would add the `return_value=<VALUE_TO_RETURN>` parameter to the patch call. | ||
@pytest.fixture(name="bypass_get_data") | ||
def bypass_get_data_fixture(): | ||
"""Skip calls to get data from API.""" | ||
with patch.object( | ||
DWDWeatherData, "async_update", side_effect=Mock() | ||
): | ||
yield | ||
# with patch.object( | ||
# DWDWeatherForecastSensor, "async_get_data", side_effect=Mock() | ||
# ): | ||
# yield | ||
|
||
|
||
# In this fixture, we are forcing calls to async_get_data to raise an Exception. This is useful | ||
# for exception handling. | ||
@pytest.fixture(name="error_on_get_data") | ||
def error_get_data_fixture(): | ||
"""Simulate error when retrieving data from API.""" | ||
with patch.object( | ||
DWDWeatherData, "async_update", side_effect=Exception | ||
): | ||
yield | ||
# with patch.object( | ||
# DWDWeatherForecastSensor, "async_get_data", side_effect=Exception | ||
# ): | ||
# yield |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
"""Constants for tests.""" | ||
from typing import Final | ||
from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE, CONF_NAME | ||
from custom_components.dwd_weather.const import DEFAULT_WIND_DIRECTION_TYPE, CONF_WEATHER_INTERVAL, CONF_WIND_DIRECTION_TYPE, CONF_STATION_ID | ||
|
||
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME | ||
|
||
# Mock config data to be used across multiple tests | ||
MOCK_CONFIG: Final = { | ||
CONF_LATITUDE: 0.0, | ||
CONF_LONGITUDE: 0.0, | ||
CONF_NAME: "Test Name", | ||
CONF_WEATHER_INTERVAL: 24, | ||
CONF_WIND_DIRECTION_TYPE: DEFAULT_WIND_DIRECTION_TYPE, | ||
CONF_STATION_ID: "L732", | ||
} | ||
|
||
MOCK_USER_INPUT: Final = { | ||
CONF_STATION_ID: "L732", | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
# pylint: disable=protected-access,redefined-outer-name | ||
"""Test integration_blueprint setup process.""" | ||
|
||
import pytest | ||
from pytest_homeassistant_custom_component.common import MockConfigEntry | ||
|
||
from custom_components.dwd_weather import ( | ||
async_setup_entry, | ||
async_unload_entry, | ||
DWDWeatherData, | ||
) | ||
from custom_components.dwd_weather.const import DOMAIN, DWDWEATHER_DATA | ||
from homeassistant.core import HomeAssistant | ||
from homeassistant.exceptions import ConfigEntryNotReady | ||
|
||
from .const import MOCK_CONFIG | ||
|
||
|
||
# We can pass fixtures as defined in conftest.py to tell pytest to use the fixture | ||
# for a given test. We can also leverage fixtures and mocks that are available in | ||
# Home Assistant using the pytest_homeassistant_custom_component plugin. | ||
# Assertions allow you to verify that the return value of whatever is on the left | ||
# side of the assertion matches with the right side. | ||
async def test_setup_load_and_unload_entry(hass: HomeAssistant, bypass_get_data): | ||
"""Test entry setup and unload.""" | ||
# Create a mock entry so we don't have to go through config flow | ||
config_entry = MockConfigEntry(domain=DOMAIN, data=MOCK_CONFIG, entry_id="test") | ||
|
||
# Set up the entry and assert that the values set during setup are where we expect | ||
# them to be. | ||
assert await async_setup_entry(hass, config_entry) | ||
assert DOMAIN in hass.data and config_entry.entry_id in hass.data[DOMAIN] | ||
print(hass.data[DOMAIN][config_entry.entry_id]) | ||
assert isinstance( | ||
hass.data[DOMAIN][config_entry.entry_id][DWDWEATHER_DATA], DWDWeatherData | ||
) | ||
|
||
# Unload the entry and verify that the data has been removed | ||
assert await async_unload_entry(hass, config_entry) | ||
if DOMAIN in hass.data: | ||
assert config_entry.entry_id not in hass.data[DOMAIN] | ||
|
||
|
||
# async def test_setup_entry_exception(hass: HomeAssistant, error_on_get_data): | ||
# """Test ConfigEntryNotReady when API raises an exception during entry setup.""" | ||
# config_entry = MockConfigEntry(domain=DOMAIN, data=MOCK_CONFIG, entry_id="test") | ||
|
||
# # In this case we are testing the condition where async_setup_entry raises | ||
# # ConfigEntryNotReady using the `error_on_get_data` fixture which simulates | ||
# # an error. | ||
# with pytest.raises(ConfigEntryNotReady): | ||
# assert await async_setup_entry(hass, config_entry) |