Pytest / Django: Как изменить декоратор, который определяется во время сборки?
Я делаю сетевой запрос и даю ему 10-секундный таймаут.
Таймаут вызывается декоратором, который считывает ограничение по времени из settings, так что это выглядит следующим образом:
@timeout(settings.TIMEOUT).
Проблема в том, что я хочу, чтобы тест был очень быстрым, поэтому я изменяю таймаут на 0.1:
settings.TIMEOUT = 0.1
Проблема в том, что декоратор уже initialized (возможно, я использую неправильное слово) к тому времени, когда я пытаюсь его протестировать. То есть декоратор создается/определяется во время сборки, затем я меняю настройки, но слишком поздно, декоратор не считывает обновленные настройки снова.
Вот упрощенная версия:
##############
settings.py
###############
TIMEOUT = 10
###############
request_maker.py
###############
from timeout_decorator import timeout
from django.conf import settings
from time import sleep
class MakeRequest
@timeout(settings.TIMEOUT)
def make_the_request(self):
sleep(100)
###############
tests.py
###############
import pytest
from timeout_decorator import TimeoutError
from request_maker import MakeRequest
def test_make_request(settings):
settings.TIMEOUT = 0.1
mr = MakeRequest()
with pytest.raises(TimeoutError) as e:
mr.make_the_request() # < Even though TIMEOUT is 0.1, it actually times out for 10 seconds
Как я могу изменить код так, чтобы во время производства он был @timeout(10), а во время тестирования @timeout(0.1)?
У вас должна быть переменная DEBUG в вашем settings.py и предположим, что вы инициализируете эту переменную из .env, чтобы определить, является ли она производственной или нет. Затем вы можете инициализировать переменную TIMEOUT в settings.py в зависимости от переменной DEBUG следующим образом:
DEBUG = os.getenv("DEBUG") == "True"
TIMEOUT = 0.1 if DEBUG else 10
Чтобы исправить это, я сделал две вещи:
- Я изменил способ загрузки модуля:
import request_maker
- Я перезагрузил модуль после обновления настроек
settings.TIMEOUT = 0.1
reload(request_maker)
Вот полный новый код:
###############
tests.py
###############
import pytest
from timeout_decorator import TimeoutError
import request_maker
from importlib import reload
def test_make_request(settings):
settings.TIMEOUT = 0.1
reload(request_maker)
mr = request_maker.MakeRequest()
with pytest.raises(TimeoutError) as e:
mr.make_the_request() # < Sleeps for 0.1 seconds only!