Тестовый Django Pytest URL на основе настроек
У меня есть конечная точка /docs
в Django, что я хочу видеть только когда DEBUG = True
в настройках - иначе должен выкинуть 404. Моя настройка выглядит так
urls.py
urlpatterns = ...
if settings.DEBUG:
urlpatterns += [
url(r'^docs/$', SwaggerSchemaView.as_view(), name='api_docs'),
]
Однако при тестировании django не перезагружается автоматически urls.py
, что означает просто переопределение DEBUG
в True
или же False
не работает
Мои тесты выглядят примерно так
@override_settings(DEBUG=True)
@override_settings(ROOT_URLCONF='config.urls')
class APIDocsTestWithDebug(APITestCase):
# check for 200s
...
@override_settings(DEBUG=False)
@override_settings(ROOT_URLCONF='config.urls')
class APIDocsTestWithoutDebug(APITestCase):
# check for 404s
...
Теперь вот странная часть: когда я запускаю тесты по отдельности, используя pytest path/to/test.py::APIDocsTestWithDebug
а также pytest path/to/test.py::APIDocsTestWithoutDebug
Оба теста проходят. Тем не менее, если я запускаю тестовый файл в целом (pytest path/to/test.py
), APIDocsTestWithDebug
всегда терпит неудачу. Тот факт, что они работают по отдельности, но не вместе, говорит мне, что переопределение URL работает, но когда тесты выполняются в тандеме, возникает некоторая ошибка, которая портит ситуацию. Мне было интересно, сталкивался ли кто-нибудь с подобной проблемой и имеет ли совершенно другое решение, или может дать мне несколько советов относительно того, что я делаю неправильно.
3 ответа
Я боролся с той же проблемой. Дело в том, что Django загружает ваши urlpatterns
один раз при инициализации - и переопределение настроек декоратором не меняет то, что было изначально загружено.
Вот что сработало для меня - попробуйте перезагрузить свой urls
модуль (основанный на этом) и очистка кэшей URL с clear_url_caches()
до неудачных тестов:
import sys
from importlib import reload, import_module
from django.conf import settings
from django.core.urlresolvers import clear_url_caches
def reload_urlconf(urlconf=None):
clear_url_caches()
if urlconf is None:
urlconf = settings.ROOT_URLCONF
if urlconf in sys.modules:
reload(sys.modules[urlconf])
else:
import_module(urlconf)
PS: Вы также можете позже восстановить urlpatterns - просто запустите reload_urlconf
в других settings
,
Вы можете использовать @pytest.mark.urls
: https://pytest-django.readthedocs.io/en/latest/helpers.html
@pytest.mark.urls('myapp.test_urls')
def test_something(client):
assert 'Success!' in client.get('/some_url_defined_in_test_urls/').content
Вы даже можете определить URL-адреса в одном файле:
def some_view(request):
return HttpResponse(b"Success!")
urlpatterns = [
path("some-url/", some_view)
]
@pytest.mark.urls(__name__)
def test_something(client):
assert b'Success!' in client.get('/some-url/').content
Основываясь на ответе Сергея Никифорова, я реализовал пакет Pypi с контекстным менеджером для загрузки/перезагрузки URL-адресов.
Страница Github: https://github.com/karpyncho/reload-urls
Установить:
pip install karpyncho_reload_urls
тогда вы просто наследуете свой класс костюма TestCase от TestCaseReloadableURL
и вы можете просто использовать:
from karpyncho.reload_urls import TestCaseReloadableURL
class TestMyClass(TestCaseReloadableURL)
def my_test(self):
with self.reload_urls(DEBUG=True):
# put your checks here
это перезагрузит ваши настройки только в контекстном блоке
вы можете предлагать улучшения..