Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Async fixtures don't support pytest.mark.usefixtures() #124

Open
mikenerone opened this issue Sep 7, 2021 · 2 comments
Open

Async fixtures don't support pytest.mark.usefixtures() #124

mikenerone opened this issue Sep 7, 2021 · 2 comments

Comments

@mikenerone
Copy link
Member

mikenerone commented Sep 7, 2021

Async fixtures can't be used in @pytest.mark.usefixtures(...) decorators.
I'm sure this is a side-effect of the trio-fixture workaround approach explained in the docs, but it should be possible to examine the test function's marks and honor them.

@njsmith
Copy link
Member

njsmith commented Sep 8, 2021

I guess this has the same cause as #123 -- we're not properly querying pytest to figure out the list of fixtures. I would guess fixing one would also fix the other.

@Badg
Copy link

Badg commented Feb 2, 2024

I just got bit by this too. Min viable reproduction, in case it's useful as a testcase somewhere (though probably not because of the added trio_asyncio dep):

import asyncio

import pytest
import trio
import trio_asyncio


@pytest.fixture
async def trio_asyncio_loop():
    # When a ^C happens, trio send a Cancelled exception to each running
    # coroutine. We must protect this one to avoid deadlock if it is cancelled
    # before another coroutine that uses trio-asyncio.
    with trio.CancelScope(shield=True):
        async with trio_asyncio.open_loop() as loop:
            yield loop


@pytest.mark.usefixtures('trio_asyncio_loop')
class TestMetatest:

    async def test_the_thing(self):
        await trio_asyncio.aio_as_trio(asyncio.sleep)(0)

For posterity / any wandering googlers travelers:

_____________________________________________________________________________________________________________________________ TestMetatest.test_the_thing ______________________________________________________________________________________________________________________________
self = <tests.unittests.datastores.test_postgres.TestMetatest object at 0x7fbd4be01af0>

    async def test_the_thing(self):
        from trio_asyncio import aio_as_trio
>       await aio_as_trio(asyncio.sleep)(0)

tests/unittests/datastores/test_postgres.py:21:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <trio_asyncio._adapter.Asyncio_Trio_Wrapper object at 0x7fbd4be319d0>, args = (0,), kwargs = {}, f = <coroutine object _call_defer at 0x7fbd4bd56c00>

    async def __call__(self, *args, **kwargs):
        if self.args:
            raise RuntimeError("Call 'aio_as_trio(proc)(*args)', not 'aio_as_trio(proc, *args)'")

        # We route this through _calL_defer because some wrappers require
        # running in asyncio context
        f = _call_defer(self.proc, *args, **kwargs)
>       return await self.loop.run_aio_coroutine(f)
E       AttributeError: 'NoneType' object has no attribute 'run_aio_coroutine'

The workaround is simple, though not DRY:

class TestMetatest:

    # Explicitly call for the fixture on every test case instead of using mark.usefixtures
    async def test_the_thing(self, trio_asyncio_loop):
        await trio_asyncio.aio_as_trio(asyncio.sleep)(0)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants