如何在pytest中为asyncio代码编写fixture

时间:2018-01-16 17:32:42

标签: python pytest python-asyncio

我想和pytest一起使用asyncio。

这就是我想要做的事情:

  • 在我的测试运行时运行服务器 - 停止服务器的时间 完成
  • 在一个完美的世界中,我会将服务器实现为一个夹具(使用yield)

我喜欢写这样的测试代码:

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

我尝试使用 pytest-asyncio https://pypi.python.org/pypi/pytest-asyncio)编写灯具,但无法弄清楚如何执行此操作。

我想出了这个测试(有效,但看起来很笨拙,掩盖了测试的意图):

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

如何将服务器代码提取到像文档或示例链接这样的工具中的任何帮助都将非常感激。

我认为不需要完整的服务器代码(但它在这里:https://stackoverflow.com/a/48277838/570293

1 个答案:

答案 0 :(得分:0)

就像我在我的问题中指出的那样,我不希望异步的东西膨胀我的测试用例。到目前为止,我能找到的唯一简单的工作解决方案是使用多处理。我知道process.terminate()不是"最佳方式"结束asyncio循环,但至少它可靠地工作。

# -*- 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