Async fixtures with pytest

前端 未结 2 570
陌清茗
陌清茗 2021-01-17 09:39

How do I define async fixtures and use them in async tests?

The following code, all in the same file, fails miserably. Is the fixture called plainly by the test runn

相关标签:
2条回答
  • 2021-01-17 10:00

    You only need to mark your tests as async

    @pytest.mark.asyncio
    async def test_app(create_x, auth):
        api_client, x_id = create_x
        resp = await api_client.get(f'my_res/{x_id}', headers=auth)
        assert resp.status == web.HTTPOk.status_code
    

    This tells pytest to run the test inside an event loop rather than calling it directly.

    The fixtures can be marked as normal

    @pytest.fixture
    async def create_x(api_client):
        x_id = await add_x(api_client)
        return api_client, x_id
    
    0 讨论(0)
  • Coroutine functions are not natively supported by PyTest, so you need to install additional framework for it

    • pytest-aiohttp
    • pytest-asyncio
    • pytest-trio
    • pytest-tornasync

    If you use pytest-aiohttp, your problem solves in this way

    import asyncio
    import pytest
    
    from app import db
    
    
    url = 'postgresql://postgres:postgres@localhost:5432'
    
    
    @pytest.fixture(scope='session')
    def loop():
        return asyncio.get_event_loop()
    
    
    @pytest.fixture(scope='session', autouse=True)
    async def prepare_db(loop):
        async with db.with_bind(f'{url}/postgres') as engine:
            await engine.status(db.text('CREATE DATABASE test_db'))
    
        await db.set_bind(f'{url}/test_db')
        await db.gino.create_all()
    
        yield
        await db.bind.close()
    
        async with db.with_bind(f'{url}/postgres') as engine:
            await engine.status(db.text('DROP DATABASE test_db'))
    

    Main idea is using synchronous loop-fixture which will be used by async fixtures

    0 讨论(0)
提交回复
热议问题