I have an endpoint /docs
in django that I only want to be visible when DEBUG = True
in settings - otherwise, it should throw a 404. My setup looks like this
urls.py
urlpatterns = ...
if settings.DEBUG:
urlpatterns += [
url(r'^docs/$', SwaggerSchemaView.as_view(), name='api_docs'),
]
When doing testing, though, django doesn't automatically reload urls.py
, which means simply overriding DEBUG
to True
or False
doesn't work.
My tests look something like this
@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
...
Now here's the weird part: When I run the tests individually using pytest path/to/test.py::APIDocsTestWithDebug
and pytest path/to/test.py::APIDocsTestWithoutDebug
, both tests pass. However, if I run the test file as a whole (pytest path/to/test.py
), APIDocsTestWithDebug
always fails. The fact that they work individually but not together tells me that the url override is working, but when the tests are in tandem, there is some bug that messes things up. I was wondering if anybody had come across a similar issue and either has an entirely different solution or can give me some tips as to what I'm doing wrong.
I struggled with the same issue. The thing is that Django loads your urlpatterns
once while initializing - and overriding the settings with the decorator doesn't change what was initially loaded.
Here's what worked for me - try reloading your urls
module (based on this) and clearing url caches with clear_url_caches()
before the failing test cases:
import sys
from importlib import reload, import_module
from django.conf import settings
from django.core.urlresolvers import clear_url_caches # Or -> from django.urls 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: You might also want to restore the urlpatterns later - just run reload_urlconf
within other settings
.
You can use @pytest.mark.urls
: https://pytest-django.readthedocs.io/en/latest/helpers.html#pytest.mark.urls
@pytest.mark.urls('myapp.test_urls')
def test_something(client):
assert 'Success!' in client.get('/some_url_defined_in_test_urls/').content
You could even define the URLs within the same file:
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With