freezegun icon indicating copy to clipboard operation
freezegun copied to clipboard

freezegun hangs parametrized asyncio test

Open niobos opened this issue 3 years ago • 4 comments

Hi,

First of all, thank you for creating this project. It's a real help to test time-related code in an easy an consistent way. Thank you.

I'm currently trying to debug why some of my tests hang forever. It looks like it's a combination of freezegun, parametrized tests and asyncio. Minimal test case:

import asyncio
import pytest
import freezegun


@pytest.fixture(params=[1, 2])
def number(request):
    """Returns a number"""
    return request.param


async def do_stuff(num):
    await asyncio.sleep(0.001)
    return num


@pytest.mark.asyncio
async def test_do_stuff(number):
    with freezegun.freeze_time() as frozen_datetime:
        coro = do_stuff(number)
        result = await coro
        assert result == number

The first run (with number == 1) runs fine, but the second run (with number == 2) hangs at the await coro step:

$ pytest -v tests/freezegun_test.py
================================ test session starts =================================
platform darwin -- Python 3.9.1, pytest-6.2.4, py-1.10.0, pluggy-0.13.1 -- /<redacted>/venv/bin/python3
cachedir: .pytest_cache
rootdir: /<redacted>
plugins: asyncio-0.15.1
collected 2 items                                                                    

tests/freezegun_test.py::test_do_stuff[1] ^C

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! KeyboardInterrupt !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
/usr/local/Cellar/[email protected]/3.9.1_3/Frameworks/Python.framework/Versions/3.9/lib/python3.9/selectors.py:562: KeyboardInterrupt
(to show a full traceback on KeyboardInterrupt use --full-trace)
=============================== no tests ran in 0.03s ================================
Task was destroyed but it is pending!
task: <Task pending name='Task-1' coro=<test_do_stuff() done, defined at /<redacted>/tests/freezegun_test.py:17> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x102539a90>()]>>

Other combinations work:

  • Running without freezegun
  • Running a single test (non-parametrized, or parametrized with a single run)
  • non-asyncio calls

How can I help to identify and fix this bug?

Version details $ python -V Python 3.9.1

$ pip list Package Version


attrs 21.2.0 freezegun 1.1.0 iniconfig 1.1.1 packaging 20.9 pip 20.2.3 pluggy 0.13.1 py 1.10.0 pyparsing 2.4.7 pytest 6.2.4 pytest-asyncio 0.15.1 python-dateutil 2.8.1 setuptools 49.2.1 six 1.16.0 toml 0.10.2 WARNING: You are using pip version 20.2.3; however, version 21.1.2 is available. You should consider upgrading via the '/Users/niels/nextcloud/src/velbuspy/venv/bin/python3 -m pip install --upgrade pip' command.

niobos avatar Jun 08 '21 19:06 niobos

I've got a similar problem when upgrading from 1.0.0 to 1.1.0. In my case though, I don't have a parametrized test. It simply hangs as soon as I do await asyncio.sleep(0.1)

Sebadst avatar Jun 09 '21 08:06 Sebadst

It looks related to this issue. If I put tick=True it doesn't hang, even though, of course, the behavior is not the same.

Otherwise, if you don't really need to sleep but to give back control to the event loop, you can do await asyncio.sleep(0). That seems to work

Sebadst avatar Jun 09 '21 08:06 Sebadst

In my case though, I don't have a parametrized test. It simply hangs as soon as I do await asyncio.sleep(0.1)

Hmm, interesting. I assumed it was something that freezegun didn't clean up properly in the __exit__() of the first run, since it only failed on the second run. But maybe it's not "supposed to work" at all, and the "bug" is that it works the first time...

I'll try to bisect some versions to see if that would pinpoint this issue down.

niobos avatar Jun 09 '21 10:06 niobos

Some additional data:

When running outside of pytest, it hangs on the first try (instead of 2nd run in the pytest-case):

async def do_stuff_frozen():
    with freezegun.freeze_time() as frozen_datetime:
        coro = do_stuff(1)
        result = await coro

asyncio.get_event_loop().run_until_complete(do_stuff_frozen())

Downgrading to freezegun==1.0.0 makes this issue disappear. Bisecting tells me that 8938a6913f12d64b483694ef0df3fb83d5fba165 introduced this issue.

niobos avatar Jun 09 '21 17:06 niobos

Hi, I am having similar issues with asyncio and freezegun==1.2.2. As far as I understood this fix should be a part of freezegun==1.3.0 release. When can we expect 1.3.0 to be available in pypi?

Losik avatar May 23 '23 11:05 Losik

@Losik I would recommend trying to move to time-machine. Freezegun is mostly not maintained.

boxed avatar May 23 '23 11:05 boxed