8

I am trying to write tests for aiohttp application. I am using pytest-aiohttp plugin. My intention is to initialize and run the application once before first test execution and tear down after all tests finished. pytest-aiohttp fixtures like 'loop', 'test_client' are very helpful but they have scope='function' which means I can not use them from my own fixture with scope='session'. Is there a way to workaround this? And if not then what would be a proper approach for achieving my goal without using built-in fixtures? My code is as follows (conftest.py)

@pytest.fixture()
def client(test_client, loop):
    app = init(loop)
    return loop.run_until_complete(test_client(app))

My tests then use this

class TestGetAlerts:
async def test_get_login_url(self, client):
    resp = await client.get('/api/get_login_url')
    assert resp.status == 200

So my fixture 'client' runs for every test, which is what i want to avoid

Belerafon
  • 488
  • 4
  • 13

1 Answers1

4

test_client fixture is a simple wrapper around TestServer and TestClient classes from aiohttp.test_utils.

You can craft your own version of the fixture with 'session' scope.

But this way has own problems: tests should be isolated, in practice it means event loop recreation for every test.

But session-level aiohttp application doesn't support such loop recreation. Thus the app should be run in separate thread which makes writing test assertions much harder.

In my practice aiohttp application starts instantly but things like DB schema migration and DB fixtures applying takes time. These activities could be implemented in session scope easy as separate fixtures but app starting/stopping should be performed inside every test.

Andrew Svetlov
  • 16,730
  • 8
  • 66
  • 69
  • If I have a session scoped fixture which just performs side-effects independent of the loop, why can't I depend on this in a test that uses the function scoped loop fixture? – CMCDragonkai Aug 13 '20 at 07:01
  • 1
    Can you provide an example of doing this with `session` scope. Right now this doesn't work for me. Since my application has a subprocess that attaches tensorflow which is then locked into the GPU. Right now having to recreate the app for each test means that the GPU has to be reinitialized each time. This slows down the tests significantly. – CMCDragonkai Sep 03 '20 at 08:32
  • Turns out I just had to do: ``` @pytest.fixture(scope='session') def loop(): return asyncio.get_event_loop() ``` – CMCDragonkai May 06 '21 at 06:13