I have a working basic example of a setup and teardown fixture in Pytest:
@pytest.fixture()
def setup_and_teardown():
# Setup
print('setup')
# Yield some variable to the test
yield 'v'
# Teardown
print('teardown')
async def test_me(setup_and_teardown):
"""Test successful experiment retrieval."""
variable = db_data_setup_and_teardown
# Call the method
result = my_func_that_i_wrote_so_well(variable)
# Assertions
assert result == 'v2'
It works. But now I need async support. Both my setup and teardown steps are async. So I tried to do:
@pytest.fixture()
async def setup_and_teardown():
# Setup
print('setup')
await my_setup_func()
# Yield some variable to the test
yield 'v'
# Teardown
print('teardown')
await my_teardown_func()
but then variable = db_data_setup_and_teardown results in variable being an 'async_generator' object. If I try to use variable = await db_data_setup_and_teardown instead, then I just get the error
TypeError: object async_generator can't be used in 'await' expression
What is the correct way to convert this pytest fixture into something async?
It turns out that Pytest does NOT support async fixtures out of the box. It is necessary to install a third-party package (and pytest plugin) called pytest-asyncio.
Then I needed to decorate the fixture with @pytest_asyncio.fixture() instead of @pytest.fixture(), and as @J_H had mentioned, also decorate the test function itself with @pytest.mark.asyncio. Those two changes alone fix the problem.
So in summary the resulting code is:
import pytest
import pytest_asyncio
@pytest_asyncio.fixture()
async def setup_and_teardown():
# Setup
print('setup')
await my_setup_func()
# Yield some variable to the test
yield 'v'
# Teardown
print('teardown')
await my_teardown_func()
@pytest.mark.asyncio
async def test_me(setup_and_teardown):
"""Test successful experiment retrieval."""
variable = db_data_setup_and_teardown
# Call the method
result = my_func_that_i_wrote_so_well(variable)
# Assertions
assert result == 'v2'
and it works!