mirror of
https://github.com/home-assistant/core.git
synced 2026-08-24 10:13:52 -05:00
Give the test loop factory a fallback for fixture-only runners
pytest-asyncio only parametrizes the loop factory for async tests, so a synchronous test pulling in an async fixture built that fixture's runner with a stock loop, losing the executor and the loop.time binding that the policy used to supply everywhere. Overriding _asyncio_loop_factory keeps the parametrized value when there is one and falls back to create_event_loop otherwise. The added tests cover both the synchronous and the async path. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PRmnu5HiXQUaHcHnNCvBSU
This commit is contained in:
@@ -38,6 +38,7 @@ import freezegun
|
||||
import multidict
|
||||
import pytest
|
||||
import pytest_asyncio
|
||||
from pytest_asyncio.plugin import LoopFactory
|
||||
import pytest_socket
|
||||
import requests_mock
|
||||
import respx
|
||||
@@ -158,6 +159,17 @@ def pytest_asyncio_loop_factories() -> dict[str, Callable[[], AbstractEventLoop]
|
||||
return {"homeassistant": runner.create_event_loop}
|
||||
|
||||
|
||||
@pytest.fixture(scope="session", autouse=True)
|
||||
def _asyncio_loop_factory(request: pytest.FixtureRequest) -> LoopFactory:
|
||||
"""Cover the runners pytest_asyncio_loop_factories does not reach.
|
||||
|
||||
pytest-asyncio only parametrizes the factory for async tests, so a
|
||||
synchronous test pulling in an async fixture would otherwise build that
|
||||
fixture's runner with a stock loop.
|
||||
"""
|
||||
return getattr(request, "param", None) or runner.create_event_loop
|
||||
|
||||
|
||||
# Capture the real socket functions before any test patches them
|
||||
_real_getaddrinfo = socket.getaddrinfo
|
||||
|
||||
|
||||
@@ -434,3 +434,21 @@ def test_ensure_single_execution_sequential_runs(tmp_path: Path) -> None:
|
||||
|
||||
# Lock file should still exist after second run (not unlinked)
|
||||
assert lock_file_path.exists()
|
||||
|
||||
|
||||
def _assert_hass_event_loop(loop: asyncio.AbstractEventLoop) -> None:
|
||||
"""Assert the loop carries the Home Assistant customizations."""
|
||||
assert loop.time is runner.monotonic
|
||||
assert isinstance(loop._default_executor, executor.InterruptibleThreadPoolExecutor)
|
||||
|
||||
|
||||
def test_sync_test_gets_hass_event_loop(hass: HomeAssistant) -> None:
|
||||
"""Test a synchronous test builds the async hass fixture on our loop."""
|
||||
# pytest-asyncio only parametrizes the loop factory for async tests
|
||||
_assert_hass_event_loop(hass.loop)
|
||||
|
||||
|
||||
async def test_async_test_gets_hass_event_loop(hass: HomeAssistant) -> None:
|
||||
"""Test an async test runs on our loop."""
|
||||
_assert_hass_event_loop(asyncio.get_running_loop())
|
||||
_assert_hass_event_loop(hass.loop)
|
||||
|
||||
Reference in New Issue
Block a user