pytest-dev/pytest-asyncio

Testing an internally async module breaks async tests that come after

anordal opened this issue · 4 comments

Am I doing anything wrong here? This used to work until recently. The error message looks a lot like #209.

import asyncio
import pytest


async def internally_async_impl() -> int:
    return 0


def innocent_unrelated() -> int:
    return asyncio.run(internally_async_impl())


# Passes
@pytest.mark.asyncio
async def test_asyncio_before() -> None:
    await asyncio.sleep(0)


# Passes
def test_innocent_unrelated_module() -> None:
    innocent_unrelated()


# Fails
@pytest.mark.asyncio
async def test_asyncio_after() -> None:
    await asyncio.sleep(0)

The third test fails because the second stole the event loop:

==== ERRORS ====
____ ERROR at setup of test_asyncio_after ____

fixturedef = <FixtureDef argname='event_loop' scope='function' baseid=''>, request = <SubRequest 'event_loop' for <Function test_asyncio_after>>

    @pytest.hookimpl(hookwrapper=True)
    def pytest_fixture_setup(fixturedef, request):
        """Adjust the event loop policy when an event loop is produced."""
        if fixturedef.argname == "event_loop":
            outcome = yield
            loop = outcome.get_result()
            policy = asyncio.get_event_loop_policy()
>           old_loop = policy.get_event_loop()

/usr/local/lib/python3.9/dist-packages/pytest_asyncio/plugin.py:94: 
_ _ _

self = <asyncio.unix_events._UnixDefaultEventLoopPolicy object at 0x7f1a0856e3a0>

    def get_event_loop(self):
        """Get the event loop for the current context.
    
        Returns an instance of EventLoop or raises an exception.
        """
        if (self._local._loop is None and
                not self._local._set_called and
                threading.current_thread() is threading.main_thread()):
            self.set_event_loop(self.new_event_loop())
    
        if self._local._loop is None:
>           raise RuntimeError('There is no current event loop in thread %r.'
                               % threading.current_thread().name)
E           RuntimeError: There is no current event loop in thread 'MainThread'.

/usr/lib/python3.9/asyncio/events.py:642: RuntimeError

Workaround (found by accident, I don't know why this works):

 # Passes
+@pytest.mark.asyncio
 def test_innocent_unrelated_module() -> None:
     innocent_unrelated()

This is with pytest-asyncio 0.15.0.

Can you check master?

Can you check master

It wasn't too easy to get to a standalone pytest-asyncio setup. E.g. in virtualenv:

ModuleNotFoundError: No module named 'pytest_asyncio.plugin'; 'pytest_asyncio' is not a package

I believe this should be fixed by 0.15.1!

Indeed, it works after updating to 0.15.1.

Thank you Tinche, for the swift fix!