3

I want to use asyncio together with pytest.

here is what I want to do:

  • run a server while my test is running - stop the server when it is finished
  • in a perfect world I would implement the server as a fixture (using yield)

I like to write test code like this:

def test_add(svr_fixture):
    await asyncio.sleep(100)
    assert m.add(1, 2) == 3   # I like the readability of this and want to restore it

I tried to write the fixture with pytest-asyncio (https://pypi.python.org/pypi/pytest-asyncio) but could not figure out how to do this.

What I came up with it this test (works but it looks clumsy and disguises the intention of the test):

def test_add():
    async def do_it():
        await asyncio.sleep(100)
        return m.add(1, 2)

    loop = asyncio.get_event_loop()
    coro = loop.create_server(server.ServerProtocol, '127.0.0.1', 8023)
    asyncio.async(coro)
    res = loop.run_until_complete(do_it())
    assert res == 3

Any help on how to extract the server code into a fixture like a link to docs or a sample would be much appreciated.

I do not think the complete server code is necessary (but it is here: https://stackoverflow.com/a/48277838/570293)

moin moin
  • 2,263
  • 5
  • 32
  • 51
  • In a similar setting where I had to run twisted-based code, I had to spawn a separate process with the server, instead of trying to play with restarting the reactor within the same Python VM. It's slightly slower but offers very good isolation, and works in parallel using pytest-xdist. – 9000 Jan 16 '18 at 18:56

1 Answers1

0

Like I pointed out in my question I do not want the async stuff to bloat up my testcases. The only simple working solution I could find so far is to use multiprocessing. I understand that process.terminate() is not the "optimal way" to end the asyncio loop but at least it works reliably.

# -*- coding: utf-8 -*-
import time
from multiprocessing import Process

import pytest
from my_server import server


@pytest.fixture
def fake_server():
    p = Process(target=server.run, args=())
    p.start()

    yield
    p.terminate()


def test_add2(fake_server):
    time.sleep(30)
    assert m.add(1, 2) == 3
moin moin
  • 2,263
  • 5
  • 32
  • 51