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

Pytest failing - ScopeMismatch: You tried to access the 'function' scoped fixture 'event_loop' with a 'session' scoped request object, involved factories #638

Closed
b177y opened this issue Feb 7, 2021 · 3 comments

Comments

@b177y
Copy link

b177y commented Feb 7, 2021

Describe the bug
Trying to add testing with pytest, getting ScopeMismatch: You tried to access the 'function' scoped fixture 'event_loop' with a 'session' scoped request object, involved factories.

I understand that I'm probably doing something wrong but the documentation only covers the initializer and not how to run tests with pytest, so if anyone could point me to an example that would be great!

To Reproduce

import pytest
import os
from tortoise.contrib import test
from tortoise.contrib.test import finalizer, initializer
from models import User


@pytest.fixture(scope="session", autouse=True)
@pytest.mark.asyncio
async def initialize_tests(request):
    db_url = os.environ.get("TORTOISE_TEST_DB", "sqlite://:memory:")
    initializer(["models"], db_url=db_url, app_label="models")
    request.addfinalizer(finalizer)
    await User.create(username="joebloggs",
                      firstname="Joe",
                      lastname="Bloggs",
                      admin=False,
                      email="joe@example.com",
                      pw_hash="test")


@pytest.mark.asyncio
async def test_something():
    u1 = await User.all().first()
    assert u1.username == "joebloggs"

Expected behavior
Test should run successfully

Additional context

I have tried using pytest with the

from tortoise.contrib import test

class TestSomething(test.TestCase):
    def test_something(self):

which also failed.

Also getting warning

asynctest/mock.py:434: DeprecationWarning: "@coroutine" decorator is deprecated since Python 3.8, use "async def" instead
    def wait(self, skip=0):

which i think has been mentioned in another issue and is not fatal (and not related to my issue but thought id mention it for full context)

@yeraydiazdiaz
Copy link

I got this error as well, it seems to be related to defining an async fixture with a non-function scope, from pytest-asyncio's README

All scopes are supported, but if you use a non-function scope you will need to redefine the event_loop fixture to have the same or broader scope. Async fixtures need the event loop, and so must have the same or narrower scope than the event_loop fixture.

So the solution is to redefine the event_loop fixture to have a session scope:

@pytest.fixture(scope="session")
def event_loop():
    return asyncio.get_event_loop()

@jrversteegh
Copy link

@pytest.fixture(scope="session")
def event_loop():
    return asyncio.get_event_loop()

This works but generates a warning, but the example in the pytest docs you linked to doesn't:

@pytest.fixture(scope="session")
def event_loop():
    """Overrides pytest default function scoped event loop"""
    policy = asyncio.get_event_loop_policy()
    loop = policy.new_event_loop()
    yield loop
    loop.close()

@copdips
Copy link

copdips commented Sep 1, 2023

@pytest.fixture(scope="session")
def event_loop():
    """Overrides pytest default function scoped event loop"""
    policy = asyncio.get_event_loop_policy()
    loop = policy.new_event_loop()
    yield loop
    loop.close()

(at least for python 3.10+) asyncio.get_event_loop() returns the running event loop or creates a new one if not exists, so it could be simplifed by:

@pytest.fixture(scope="session")
def event_loop():
    loop = asyncio.get_event_loop()
    yield loop
    loop.close()

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

5 participants