如何使用fixture在pytest中超时异步测试? [英] How to timeout an async test in pytest with fixture?

查看:42
本文介绍了如何使用fixture在pytest中超时异步测试?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在测试一个可能会死锁的异步函数.我尝试添加一个装置来限制该函数在引发故障之前仅运行 5 秒,但到目前为止还没有奏效.

I am testing an async function that might get deadlocked. I tried to add a fixture to limit the function to only run for 5 seconds before raising a failure, but it hasn't worked so far.

设置:

pipenv --python==3.6
pipenv install pytest==4.4.1
pipenv install pytest-asyncio==0.10.0

代码:

import asyncio
import pytest

@pytest.fixture
def my_fixture():
  # attempt to start a timer that will stop the test somehow
  asyncio.ensure_future(time_limit())
  yield 'eggs'


async def time_limit():
  await asyncio.sleep(5)
  print('time limit reached')     # this isn't printed
  raise AssertionError


@pytest.mark.asyncio
async def test(my_fixture):
  assert my_fixture == 'eggs'
  await asyncio.sleep(10)
  print('this should not print')  # this is printed
  assert 0

--

Mikhail 的解决方案工作正常.不过,我找不到将它合并到装置中的方法.

Mikhail's solution works fine. I can't find a way to incorporate it into a fixture, though.

推荐答案

使用超时限制函数(或代码块)的便捷方法是使用 异步超时 模块.您可以在测试函数中使用它,或者,例如,创建一个装饰器.与夹具不同,它允许为每个测试指定具体时间:

Convenient way to limit function (or block of code) with timeout is to use async-timeout module. You can use it inside your test function or, for example, create a decorator. Unlike with fixture it'll allow to specify concrete time for each test:

import asyncio
import pytest
from async_timeout import timeout


def with_timeout(t):
    def wrapper(corofunc):
        async def run(*args, **kwargs):
            with timeout(t):
                return await corofunc(*args, **kwargs)
        return run       
    return wrapper


@pytest.mark.asyncio
@with_timeout(2)
async def test_sleep_1():
    await asyncio.sleep(1)
    assert 1 == 1


@pytest.mark.asyncio
@with_timeout(2)
async def test_sleep_3():
    await asyncio.sleep(3)
    assert 1 == 1

为具体时间创建装饰器并不难(with_timeout_5 = partial(with_timeout, 5)).

It's not hard to create decorator for concrete time (with_timeout_5 = partial(with_timeout, 5)).

我不知道如何创建纹理(如果你真的需要夹具),但上面的代码可以提供起点.也不确定是否有更好地实现目标的通用方法.

I don't know how to create texture (if you really need fixture), but code above can provide starting point. Also not sure if there's a common way to achieve goal better.

这篇关于如何使用fixture在pytest中超时异步测试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆