#python #pytest #python-asyncio #semaphore #pytest-xdist
#python #pytest #python-asyncio #семафор #pytest-xdist
Вопрос:
У меня есть несколько тестовых файлов, каждый из которых имеет асинхронный параметр, который выглядит следующим образом:
@pytest.fixture(scope="module")
def event_loop(request):
loop = asyncio.get_event_loop_policy().new_event_loop()
yield loop
loop.close()
@pytest.fixture(scope="module")
async def some_fixture():
return await make_fixture()
Я использую xdist для распараллеливания. Кроме того, у меня есть этот декоратор:
@toolz.curry
def throttle(limit, f):
semaphore = asyncio.Semaphore(limit)
@functools.wraps(f)
async def wrapped(*args, **kwargs):
async with semaphore:
return await f(*args, **kwargs)
return wrapped
и у меня есть функция, использующая это:
@throttle(10)
def f():
...
Теперь f
вызывается из нескольких тестовых файлов, и я получаю исключение, сообщающее мне, что я не могу использовать семафор из разных циклов событий.
Я попытался перейти к привязке цикла событий на уровне сеанса:
@pytest.fixture(scope="session", autouse=True)
def event_loop(request):
loop = asyncio.get_event_loop_policy().new_event_loop()
yield loop
loop.close()
Но это только дало мне:
Несоответствие области действия: вы пытались получить доступ к прибору с привязкой к ‘функции’ ‘event_loop’ с помощью объекта запроса с привязкой к модулю, задействованного фабриками
Возможно ли вообще, чтобы xdist async fixture semaphore работали вместе?
Ответ №1:
В конечном итоге он заработал, используя следующее conftest.py
:
import asyncio
import pytest
@pytest.fixture(scope="session")
def event_loop():
return asyncio.get_event_loop()
Комментарии:
1. Это сработало для меня, но, похоже, ошибка с pytest-asyncio
2. Это не ошибка, параметр event_loop pytest-asyncio по умолчанию имеет значение «функция», поэтому вы получаете новый event_loop для каждой тестовой функции. Следовательно, другое асинхронное устройство не может работать в течение всего сеанса, поскольку это будет охватывать несколько разных циклов событий. Вам нужно переопределить привязку event_loop с нужной вам областью, как показано в ответе Uri. Смотрите «Приспособления» в pypi.org/project/pytest-asyncio