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

Чтобы исправить это, я сделал две вещи:

  1. Я изменил способ загрузки модуля:
import request_maker
  1. Я перезагрузил модуль после обновления настроек
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!

Вернуться на верх