66from contextlib import asynccontextmanager
77import functools
88import itertools
9+ import gc
910from json import JSONDecoder , loads
1011import logging
1112import sqlite3
1213import ssl
1314import threading
1415from typing import Any
1516from unittest .mock import AsyncMock , MagicMock , Mock , patch
17+ import warnings
1618
1719from aiohttp import client
1820from aiohttp .pytest_plugin import AiohttpClient
@@ -188,12 +190,14 @@ async def guard_func(*args, **kwargs):
188190
189191
190192@pytest .fixture (autouse = True )
191- def verify_cleanup ():
193+ def verify_cleanup (event_loop : asyncio . AbstractEventLoop ):
192194 """Verify that the test has cleaned up resources correctly."""
193195 threads_before = frozenset (threading .enumerate ())
194-
196+ tasks_before = asyncio . all_tasks ( event_loop )
195197 yield
196198
199+ event_loop .run_until_complete (event_loop .shutdown_default_executor ())
200+
197201 if len (INSTANCES ) >= 2 :
198202 count = len (INSTANCES )
199203 for inst in INSTANCES :
@@ -204,6 +208,26 @@ def verify_cleanup():
204208 for thread in threads :
205209 assert isinstance (thread , threading ._DummyThread )
206210
211+ # Warn and clean-up lingering tasks and timers
212+ # before moving on to the next test.
213+ tasks = asyncio .all_tasks (event_loop ) - tasks_before
214+ for task in tasks :
215+ warnings .warn (f"Linger task after test { task } " )
216+ task .cancel ()
217+ if tasks :
218+ event_loop .run_until_complete (asyncio .wait (tasks ))
219+
220+ for handle in event_loop ._scheduled : # pylint: disable=protected-access
221+ if not handle .cancelled ():
222+ warnings .warn (f"Lingering timer after test { handle } " )
223+ handle .cancel ()
224+
225+ # Make sure garbage collect run in same test as allocation
226+ # this is to mimic the behavior of pytest-aiohttp, and is
227+ # required to avoid warnings from spilling over into next
228+ # test case.
229+ gc .collect ()
230+
207231
208232@pytest .fixture (autouse = True )
209233def bcrypt_cost ():
@@ -382,7 +406,7 @@ def exc_handle(loop, context):
382406
383407
384408@pytest .fixture
385- async def stop_hass ():
409+ async def stop_hass (event_loop ):
386410 """Make sure all hass are stopped."""
387411 orig_hass = ha .HomeAssistant
388412
@@ -403,6 +427,7 @@ def mock_hass():
403427 with patch .object (hass_inst .loop , "stop" ):
404428 await hass_inst .async_block_till_done ()
405429 await hass_inst .async_stop (force = True )
430+ await event_loop .shutdown_default_executor ()
406431
407432
408433@pytest .fixture
0 commit comments