Skip to content

Async fixture with autouse=True not executing properly in test #518

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

Closed
gabriel-frattini opened this issue Mar 23, 2023 · 2 comments
Closed
Labels

Comments

@gabriel-frattini
Copy link

  • [✅ ] a detailed description of the bug or problem you are having
  • [✅ ] output of pip list from the virtual environment you are using
  • [ ✅] pytest and operating system versions
  • [ ✅] minimal example if possible

Description:

When using an asyncio fixture with pytest, the teardown fixture is not executing properly. The teardown fixture is meant to run after test_foo and print "teardown", then await for one second before finishing. However, when the yield statement is included in the fixture, nothing gets printed to the console. If the yield statement is removed, nothing still gets printed but I get a warning: "RuntimeWarning: coroutine 'teardown' was never awaited". I don't understand this behaviour, can someone help me understand?

Steps to reproduce:

# test_foo.py

import pytest
import asyncio


@pytest.fixture(scope="function", autouse=True)
@pytest.mark.asyncio
async def teardown():
    yield
    print("teardown")
    await asyncio.sleep(1)


def test_foo():
    assert True

run pytest test_foo.py -s

Expected result:

The teardown fixture should run after the test function, print "teardown", and await for one second before finishing.

Actual result:

If the yield statement is included, "teardown" does not get printed.
If the yield statement is removed, "teardown" does still not get print but I get a warning:
"RuntimeWarning: coroutine 'teardown' was never awaited".

Environment:

Python version: 3.11.0
Pytest version: 7.2.0
Operating system: Mac OS 13.2.1

Pip list:

Package Version


attrs 22.2.0
iniconfig 2.0.0
maturin 0.14.12
packaging 23.0
pip 22.3
pluggy 1.0.0
pydantic 1.10.2
pyo3-asyncio-example 0.1.0
pytest 7.2.0
pytest-asyncio 0.20.3
python-dotenv 0.19.1
setuptools 65.5.0
typing_extensions 4.4.0

@gabriel-frattini
Copy link
Author

I found a way to make it work but It would be better to use an async fixture with autouse=True

# test_foo.py

import pytest
import asyncio

async def async_teardown():
    print("teardown")
    await asyncio.sleep(1)

@pytest.fixture(scope="function", autouse=True)
def teardown():
    yield
    asyncio.run(async_teardown())


def test_foo():
    assert True

@seifertm
Copy link
Contributor

Thanks for the great bug report!

The problem with your code is that it uses @pytest.fixture(…) in strict mode. The use of @pytest.fixture for async fixtures only makes sense with auto mode, whereas you should use @pytest_asyncio.fixture in strict mode.
Please refer to the docs about Test discovery modes and let me know if things are still unclear.

I'll see if it's possible to add a corresponding warning when using @pytest.fixture for async functions in strict mode, as it's not clear from the code why it doesn't work.

@seifertm seifertm closed this as not planned Won't fix, can't repro, duplicate, stale Mar 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants