Complete test coverage for OpenSky (#97863)

* Use mockobject for OpenSky testing

* Complete test coverage for OpenSky

* Complete test coverage for OpenSky

* Use method patching
This commit is contained in:
Joost Lekkerkerker 2023-08-06 19:39:24 +02:00 committed by GitHub
parent 0535578440
commit 42bca0f94a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 317 additions and 12 deletions

View File

@ -863,7 +863,6 @@ omit =
homeassistant/components/openhome/const.py homeassistant/components/openhome/const.py
homeassistant/components/openhome/media_player.py homeassistant/components/openhome/media_player.py
homeassistant/components/opensensemap/air_quality.py homeassistant/components/opensensemap/air_quality.py
homeassistant/components/opensky/sensor.py
homeassistant/components/opentherm_gw/__init__.py homeassistant/components/opentherm_gw/__init__.py
homeassistant/components/opentherm_gw/binary_sensor.py homeassistant/components/opentherm_gw/binary_sensor.py
homeassistant/components/opentherm_gw/climate.py homeassistant/components/opentherm_gw/climate.py

View File

@ -1,5 +1,6 @@
"""Configure tests for the OpenSky integration.""" """Configure tests for the OpenSky integration."""
from collections.abc import Awaitable, Callable from collections.abc import Awaitable, Callable
import json
from unittest.mock import patch from unittest.mock import patch
import pytest import pytest
@ -10,7 +11,7 @@ from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE, CONF_RADIUS
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from tests.common import MockConfigEntry from tests.common import MockConfigEntry, load_fixture
ComponentSetup = Callable[[MockConfigEntry], Awaitable[None]] ComponentSetup = Callable[[MockConfigEntry], Awaitable[None]]
@ -32,6 +33,23 @@ def mock_config_entry() -> MockConfigEntry:
) )
@pytest.fixture(name="config_entry_altitude")
def mock_config_entry_altitude() -> MockConfigEntry:
"""Create Opensky entry with altitude in Home Assistant."""
return MockConfigEntry(
domain=DOMAIN,
title="OpenSky",
data={
CONF_LATITUDE: 0.0,
CONF_LONGITUDE: 0.0,
},
options={
CONF_RADIUS: 10.0,
CONF_ALTITUDE: 12500.0,
},
)
@pytest.fixture(name="setup_integration") @pytest.fixture(name="setup_integration")
async def mock_setup_integration( async def mock_setup_integration(
hass: HomeAssistant, hass: HomeAssistant,
@ -40,9 +58,10 @@ async def mock_setup_integration(
async def func(mock_config_entry: MockConfigEntry) -> None: async def func(mock_config_entry: MockConfigEntry) -> None:
mock_config_entry.add_to_hass(hass) mock_config_entry.add_to_hass(hass)
json_fixture = load_fixture("opensky/states.json")
with patch( with patch(
"python_opensky.OpenSky.get_states", "python_opensky.OpenSky.get_states",
return_value=StatesResponse(states=[], time=0), return_value=StatesResponse.parse_obj(json.loads(json_fixture)),
): ):
assert await async_setup_component(hass, DOMAIN, {}) assert await async_setup_component(hass, DOMAIN, {})
await hass.async_block_till_done() await hass.async_block_till_done()

View File

@ -0,0 +1,105 @@
{
"time": 1691244533,
"states": [
{
"icao24": "3c6708",
"callsign": "DLH459 ",
"origin_country": "Germany",
"time_position": 1691244522,
"last_contact": 1691244522,
"longitude": 5.4445,
"latitude": 52.2991,
"baro_altitude": 12496.8,
"on_ground": false,
"velocity": 259.73,
"true_track": 134.84,
"vertical_rate": 0,
"sensors": null,
"geo_altitude": 12710.16,
"squawk": "1151",
"spi": false,
"position_source": 0,
"category": 6
},
{
"icao24": "3c6708",
"callsign": " ",
"origin_country": "Germany",
"time_position": 1691244522,
"last_contact": 1691244522,
"longitude": 5.4445,
"latitude": 52.2991,
"baro_altitude": 12496.8,
"on_ground": false,
"velocity": 259.73,
"true_track": 134.84,
"vertical_rate": 0,
"sensors": null,
"geo_altitude": 12710.16,
"squawk": "1151",
"spi": false,
"position_source": 0,
"category": 6
},
{
"icao24": "4846df",
"callsign": "",
"origin_country": "Kingdom of the Netherlands",
"time_position": 1691244404,
"last_contact": 1691244404,
"longitude": 4.7441,
"latitude": 52.3076,
"baro_altitude": null,
"on_ground": true,
"velocity": 8.75,
"true_track": 272.81,
"vertical_rate": null,
"sensors": null,
"geo_altitude": null,
"squawk": null,
"spi": false,
"position_source": 0,
"category": 17
},
{
"icao24": "4846df",
"callsign": "DLH420 ",
"origin_country": "Kingdom of the Netherlands",
"time_position": 1691244404,
"last_contact": 1691244404,
"longitude": 4.7441,
"latitude": 52.3076,
"baro_altitude": null,
"on_ground": true,
"velocity": 8.75,
"true_track": 272.81,
"vertical_rate": null,
"sensors": null,
"geo_altitude": null,
"squawk": null,
"spi": false,
"position_source": 0,
"category": 17
},
{
"icao24": "3e3d01",
"callsign": "ECA2HL ",
"origin_country": "Germany",
"time_position": 1691244533,
"last_contact": 1691244533,
"longitude": 5.5217,
"latitude": 52.4561,
"baro_altitude": 12500.8,
"on_ground": false,
"velocity": 201.9,
"true_track": 82.39,
"vertical_rate": 0,
"sensors": null,
"geo_altitude": 12733.02,
"squawk": "1071",
"spi": false,
"position_source": 0,
"category": 1
}
]
}

View File

@ -0,0 +1,45 @@
{
"time": 1691244533,
"states": [
{
"icao24": "4846df",
"callsign": "",
"origin_country": "Kingdom of the Netherlands",
"time_position": 1691244404,
"last_contact": 1691244404,
"longitude": 4.7441,
"latitude": 52.3076,
"baro_altitude": null,
"on_ground": true,
"velocity": 8.75,
"true_track": 272.81,
"vertical_rate": null,
"sensors": null,
"geo_altitude": null,
"squawk": null,
"spi": false,
"position_source": 0,
"category": 17
},
{
"icao24": "3e3d01",
"callsign": "ECA2HL ",
"origin_country": "Germany",
"time_position": 1691244533,
"last_contact": 1691244533,
"longitude": 5.5217,
"latitude": 52.4561,
"baro_altitude": 12500.8,
"on_ground": false,
"velocity": 201.9,
"true_track": 82.39,
"vertical_rate": 0,
"sensors": null,
"geo_altitude": 12733.02,
"squawk": "1071",
"spi": false,
"position_source": 0,
"category": 1
}
]
}

View File

@ -0,0 +1,42 @@
# serializer version: 1
# name: test_sensor
StateSnapshot({
'attributes': ReadOnlyDict({
'attribution': 'Information provided by the OpenSky Network (https://opensky-network.org)',
'friendly_name': 'OpenSky',
'icon': 'mdi:airplane',
'unit_of_measurement': 'flights',
}),
'context': <ANY>,
'entity_id': 'sensor.opensky',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': '2',
})
# ---
# name: test_sensor_altitude
StateSnapshot({
'attributes': ReadOnlyDict({
'attribution': 'Information provided by the OpenSky Network (https://opensky-network.org)',
'friendly_name': 'OpenSky',
'icon': 'mdi:airplane',
'unit_of_measurement': 'flights',
}),
'context': <ANY>,
'entity_id': 'sensor.opensky',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': '1',
})
# ---
# name: test_sensor_updating
list([
<Event opensky_exit[L]: callsign=DLH459, altitude=0, sensor=OpenSky, longitude=None, latitude=None, icao24=None>,
])
# ---
# name: test_sensor_updating.1
list([
<Event opensky_exit[L]: callsign=DLH459, altitude=0, sensor=OpenSky, longitude=None, latitude=None, icao24=None>,
<Event opensky_entry[L]: callsign=DLH459, altitude=12496.8, sensor=OpenSky, longitude=5.4445, latitude=52.2991, icao24=3c6708>,
])
# ---

View File

@ -1,20 +1,115 @@
"""OpenSky sensor tests.""" """OpenSky sensor tests."""
from homeassistant.components.opensky.const import DOMAIN from datetime import timedelta
import json
from unittest.mock import patch
from python_opensky import StatesResponse
from syrupy import SnapshotAssertion
from homeassistant.components.opensky.const import (
DOMAIN,
EVENT_OPENSKY_ENTRY,
EVENT_OPENSKY_EXIT,
)
from homeassistant.config_entries import ConfigEntryState from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import CONF_PLATFORM, CONF_RADIUS, Platform from homeassistant.const import CONF_PLATFORM, CONF_RADIUS, Platform
from homeassistant.core import HomeAssistant from homeassistant.core import Event, HomeAssistant
from homeassistant.helpers import issue_registry as ir from homeassistant.helpers import issue_registry as ir
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from homeassistant.util import dt as dt_util
from .conftest import ComponentSetup
from tests.common import MockConfigEntry, async_fire_time_changed, load_fixture
LEGACY_CONFIG = {Platform.SENSOR: [{CONF_PLATFORM: DOMAIN, CONF_RADIUS: 10.0}]} LEGACY_CONFIG = {Platform.SENSOR: [{CONF_PLATFORM: DOMAIN, CONF_RADIUS: 10.0}]}
async def test_legacy_migration(hass: HomeAssistant) -> None: async def test_legacy_migration(hass: HomeAssistant) -> None:
"""Test migration from yaml to config flow.""" """Test migration from yaml to config flow."""
assert await async_setup_component(hass, Platform.SENSOR, LEGACY_CONFIG) json_fixture = load_fixture("opensky/states.json")
await hass.async_block_till_done() with patch(
entries = hass.config_entries.async_entries(DOMAIN) "python_opensky.OpenSky.get_states",
assert len(entries) == 1 return_value=StatesResponse.parse_obj(json.loads(json_fixture)),
assert entries[0].state is ConfigEntryState.LOADED ):
issue_registry = ir.async_get(hass) assert await async_setup_component(hass, Platform.SENSOR, LEGACY_CONFIG)
assert len(issue_registry.issues) == 1 await hass.async_block_till_done()
entries = hass.config_entries.async_entries(DOMAIN)
assert len(entries) == 1
assert entries[0].state is ConfigEntryState.LOADED
issue_registry = ir.async_get(hass)
assert len(issue_registry.issues) == 1
async def test_sensor(
hass: HomeAssistant,
config_entry: MockConfigEntry,
setup_integration: ComponentSetup,
snapshot: SnapshotAssertion,
):
"""Test setup sensor."""
await setup_integration(config_entry)
state = hass.states.get("sensor.opensky")
assert state == snapshot
events = []
async def event_listener(event: Event) -> None:
events.append(event)
hass.bus.async_listen(EVENT_OPENSKY_ENTRY, event_listener)
hass.bus.async_listen(EVENT_OPENSKY_EXIT, event_listener)
assert events == []
async def test_sensor_altitude(
hass: HomeAssistant,
config_entry_altitude: MockConfigEntry,
setup_integration: ComponentSetup,
snapshot: SnapshotAssertion,
):
"""Test setup sensor with a set altitude."""
await setup_integration(config_entry_altitude)
state = hass.states.get("sensor.opensky")
assert state == snapshot
async def test_sensor_updating(
hass: HomeAssistant,
config_entry: MockConfigEntry,
setup_integration: ComponentSetup,
snapshot: SnapshotAssertion,
):
"""Test updating sensor."""
await setup_integration(config_entry)
def get_states_response_fixture(fixture: str) -> StatesResponse:
json_fixture = load_fixture(fixture)
return StatesResponse.parse_obj(json.loads(json_fixture))
events = []
async def event_listener(event: Event) -> None:
events.append(event)
hass.bus.async_listen(EVENT_OPENSKY_ENTRY, event_listener)
hass.bus.async_listen(EVENT_OPENSKY_EXIT, event_listener)
async def skip_time_and_check_events() -> None:
future = dt_util.utcnow() + timedelta(minutes=15)
async_fire_time_changed(hass, future)
await hass.async_block_till_done()
assert events == snapshot
with patch(
"python_opensky.OpenSky.get_states",
return_value=get_states_response_fixture("opensky/states_1.json"),
):
await skip_time_and_check_events()
with patch(
"python_opensky.OpenSky.get_states",
return_value=get_states_response_fixture("opensky/states.json"),
):
await skip_time_and_check_events()