Improve tests for frame helper (#130046)

* Improve tests for frame helper

* Improve comments

* Add ids

* Apply suggestions from code review
This commit is contained in:
epenet 2024-11-07 17:35:58 +01:00 committed by GitHub
parent c1ecc13cb3
commit ef767c2b9f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 157 additions and 42 deletions

View file

@ -1772,10 +1772,30 @@ def mock_bleak_scanner_start() -> Generator[MagicMock]:
@pytest.fixture @pytest.fixture
def mock_integration_frame() -> Generator[Mock]: def integration_frame_path() -> str:
"""Mock as if we're calling code from inside an integration.""" """Return the path to the integration frame.
Can be parametrized with
`@pytest.mark.parametrize("integration_frame_path", ["path_to_frame"])`
- "custom_components/XYZ" for a custom integration
- "homeassistant/components/XYZ" for a core integration
- "homeassistant/XYZ" for core (no integration)
Defaults to core component `hue`
"""
return "homeassistant/components/hue"
@pytest.fixture
def mock_integration_frame(integration_frame_path: str) -> Generator[Mock]:
"""Mock where we are calling code from.
Defaults to calling from `hue` core integration, and can be parametrized
with `integration_frame_path`.
"""
correct_frame = Mock( correct_frame = Mock(
filename="/home/paulus/homeassistant/components/hue/light.py", filename=f"/home/paulus/{integration_frame_path}/light.py",
lineno="23", lineno="23",
line="self.light.is_on", line="self.light.is_on",
) )

View file

@ -1,5 +1,6 @@
"""Test the frame helper.""" """Test the frame helper."""
from typing import Any
from unittest.mock import ANY, Mock, patch from unittest.mock import ANY, Mock, patch
import pytest import pytest
@ -247,3 +248,87 @@ async def test_report_error_if_integration(
), ),
): ):
frame.report("did a bad thing", error_if_integration=True) frame.report("did a bad thing", error_if_integration=True)
@pytest.mark.parametrize(
("integration_frame_path", "keywords", "expected_error", "expected_log"),
[
pytest.param(
"homeassistant/test_core",
{},
True,
0,
id="core default",
),
pytest.param(
"homeassistant/components/test_core_integration",
{},
False,
1,
id="core integration default",
),
pytest.param(
"custom_components/test_custom_integration",
{},
False,
1,
id="custom integration default",
),
pytest.param(
"custom_components/test_integration_frame",
{"log_custom_component_only": True},
False,
1,
id="log_custom_component_only with custom integration",
),
pytest.param(
"homeassistant/components/test_integration_frame",
{"log_custom_component_only": True},
False,
0,
id="log_custom_component_only with core integration",
),
pytest.param(
"homeassistant/test_integration_frame",
{"error_if_core": False},
False,
1,
id="disable error_if_core",
),
pytest.param(
"custom_components/test_integration_frame",
{"error_if_integration": True},
True,
1,
id="error_if_integration with custom integration",
),
pytest.param(
"homeassistant/components/test_integration_frame",
{"error_if_integration": True},
True,
1,
id="error_if_integration with core integration",
),
],
)
@pytest.mark.usefixtures("mock_integration_frame")
async def test_report(
caplog: pytest.LogCaptureFixture,
keywords: dict[str, Any],
expected_error: bool,
expected_log: int,
) -> None:
"""Test report."""
what = "test_report_string"
errored = False
try:
with patch.object(frame, "_REPORTED_INTEGRATIONS", set()):
frame.report(what, **keywords)
except RuntimeError:
errored = True
assert errored == expected_error
assert caplog.text.count(what) == expected_log

View file

@ -6,7 +6,7 @@ import pathlib
import sys import sys
import threading import threading
from typing import Any from typing import Any
from unittest.mock import MagicMock, Mock, patch from unittest.mock import MagicMock, patch
from awesomeversion import AwesomeVersion from awesomeversion import AwesomeVersion
import pytest import pytest
@ -1295,26 +1295,29 @@ async def test_config_folder_not_in_path() -> None:
import tests.testing_config.check_config_not_in_path # noqa: F401 import tests.testing_config.check_config_not_in_path # noqa: F401
async def test_hass_components_use_reported( @pytest.mark.parametrize(
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, mock_integration_frame: Mock ("integration_frame_path", "expected"),
) -> None: [
"""Test that use of hass.components is reported.""" pytest.param(
mock_integration_frame.filename = ( "custom_components/test_integration_frame", True, id="custom integration"
"/home/paulus/homeassistant/custom_components/demo/light.py"
)
integration_frame = frame.IntegrationFrame(
custom_integration=True,
frame=mock_integration_frame,
integration="test_integration_frame",
module="custom_components.test_integration_frame",
relative_filename="custom_components/test_integration_frame/__init__.py",
)
with (
patch(
"homeassistant.helpers.frame.get_integration_frame",
return_value=integration_frame,
), ),
pytest.param(
"homeassistant/components/test_integration_frame",
False,
id="core integration",
),
pytest.param("homeassistant/test_integration_frame", False, id="core"),
],
)
@pytest.mark.usefixtures("mock_integration_frame")
@patch.object(frame, "_REPORTED_INTEGRATIONS", set())
async def test_hass_components_use_reported(
hass: HomeAssistant,
caplog: pytest.LogCaptureFixture,
expected: bool,
) -> None:
"""Test whether use of hass.components is reported."""
with (
patch( patch(
"homeassistant.components.http.start_http_server_and_save_config", "homeassistant.components.http.start_http_server_and_save_config",
return_value=None, return_value=None,
@ -1322,10 +1325,11 @@ async def test_hass_components_use_reported(
): ):
await hass.components.http.start_http_server_and_save_config(hass, [], None) await hass.components.http.start_http_server_and_save_config(hass, [], None)
assert ( reported = (
"Detected that custom integration 'test_integration_frame'" "Detected that custom integration 'test_integration_frame'"
" accesses hass.components.http. This is deprecated" " accesses hass.components.http. This is deprecated"
) in caplog.text ) in caplog.text
assert reported == expected
async def test_async_get_component_preloads_config_and_config_flow( async def test_async_get_component_preloads_config_and_config_flow(
@ -1987,24 +1991,29 @@ async def test_has_services(hass: HomeAssistant) -> None:
assert integration.has_services is True assert integration.has_services is True
async def test_hass_helpers_use_reported( @pytest.mark.parametrize(
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, mock_integration_frame: Mock ("integration_frame_path", "expected"),
) -> None: [
"""Test that use of hass.components is reported.""" pytest.param(
integration_frame = frame.IntegrationFrame( "custom_components/test_integration_frame", True, id="custom integration"
custom_integration=True,
frame=mock_integration_frame,
integration="test_integration_frame",
module="custom_components.test_integration_frame",
relative_filename="custom_components/test_integration_frame/__init__.py",
)
with (
patch.object(frame, "_REPORTED_INTEGRATIONS", new=set()),
patch(
"homeassistant.helpers.frame.get_integration_frame",
return_value=integration_frame,
), ),
pytest.param(
"homeassistant/components/test_integration_frame",
False,
id="core integration",
),
pytest.param("homeassistant/test_integration_frame", False, id="core"),
],
)
@pytest.mark.usefixtures("mock_integration_frame")
@patch.object(frame, "_REPORTED_INTEGRATIONS", set())
async def test_hass_helpers_use_reported(
hass: HomeAssistant,
caplog: pytest.LogCaptureFixture,
expected: bool,
) -> None:
"""Test whether use of hass.helpers is reported."""
with (
patch( patch(
"homeassistant.helpers.aiohttp_client.async_get_clientsession", "homeassistant.helpers.aiohttp_client.async_get_clientsession",
return_value=None, return_value=None,
@ -2012,10 +2021,11 @@ async def test_hass_helpers_use_reported(
): ):
hass.helpers.aiohttp_client.async_get_clientsession() hass.helpers.aiohttp_client.async_get_clientsession()
assert ( reported = (
"Detected that custom integration 'test_integration_frame' " "Detected that custom integration 'test_integration_frame' "
"accesses hass.helpers.aiohttp_client. This is deprecated" "accesses hass.helpers.aiohttp_client. This is deprecated"
) in caplog.text ) in caplog.text
assert reported == expected
async def test_manifest_json_fragment_round_trip(hass: HomeAssistant) -> None: async def test_manifest_json_fragment_round_trip(hass: HomeAssistant) -> None: