#21766 closed Bug (invalid)

Can't use reverse() or is_valid_path() with dynamically set TestCase.urls

Reported by: paulmelnikow Owned by: nobody
Component: Uncategorized Version: 1.6
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

I'm writing a component and need to override urls in a TestCase. This works fine if I set urls to a string with a module name, but the common middleware raises an exception if I specify a set of patterns.

Traceback (most recent call last):
  File "/Users/pnm/code/django-url-bug/venv/lib/python2.7/site-packages/django/test/utils.py", line 249, in inner
    return test_func(*args, **kwargs)
  File "/Users/pnm/code/django-url-bug/tests.py", line 26, in test_hello_2
    resp = self.client.get('/hello')
  File "/Users/pnm/code/django-url-bug/venv/lib/python2.7/site-packages/django/test/client.py", line 473, in get
    response = super(Client, self).get(path, data=data, **extra)
  File "/Users/pnm/code/django-url-bug/venv/lib/python2.7/site-packages/django/test/client.py", line 280, in get
    return self.request(**r)
  File "/Users/pnm/code/django-url-bug/venv/lib/python2.7/site-packages/django/test/client.py", line 426, in request
    response = self.handler(environ)
  File "/Users/pnm/code/django-url-bug/venv/lib/python2.7/site-packages/django/test/client.py", line 109, in __call__
    response = self.get_response(request)
  File "/Users/pnm/code/django-url-bug/venv/lib/python2.7/site-packages/django/core/handlers/base.py", line 196, in get_response
    response = self.handle_uncaught_exception(request, resolver, sys.exc_info())
  File "/Users/pnm/code/django-url-bug/venv/lib/python2.7/site-packages/django/core/handlers/base.py", line 90, in get_response
    response = middleware_method(request)
  File "/Users/pnm/code/django-url-bug/venv/lib/python2.7/site-packages/django/middleware/common.py", line 71, in process_request
    if (not urlresolvers.is_valid_path(request.path_info, urlconf) and
  File "/Users/pnm/code/django-url-bug/venv/lib/python2.7/site-packages/django/core/urlresolvers.py", line 573, in is_valid_path
    resolve(path, urlconf)
  File "/Users/pnm/code/django-url-bug/venv/lib/python2.7/site-packages/django/core/urlresolvers.py", line 453, in resolve
    return get_resolver(urlconf).resolve(path)
  File "/Users/pnm/code/django-url-bug/venv/lib/python2.7/site-packages/django/utils/functional.py", line 30, in wrapper
    if mem_args in cache:
TypeError: unhashable type: 'list'

If the patterns end with slashes, or if APPEND_SLASH is False, the problem goes away.

Here's code with a test example. In the test below, test_hello_2 fails with the stack trace above. test_hello_1 and test_hello_3 pass.

from django.test import TestCase
from django.test.utils import override_settings

def view_func(r):
    from django.http import HttpResponse
    return HttpResponse('Hello, World!')

class UrlTestOverriddenExplicit(TestCase):
    from django.conf.urls import patterns, url
    urls = patterns('',
        url(r'^hello/$', view_func),
    )

    def test_hello_1(self):
        resp = self.client.get('/hello/')
        self.assertEquals(resp.status_code, 200)

class UrlTestOverriddenExplicitWithoutSlash(TestCase):
    from django.conf.urls import patterns, url
    urls = patterns('',
        url(r'^hello$', view_func),
    )

    def test_hello_2(self):
        resp = self.client.get('/hello')
        self.assertEquals(resp.status_code, 200)

    @override_settings(APPEND_SLASH=False)
    def test_hello_3(self):
        resp = self.client.get('/hello')
        self.assertEquals(resp.status_code, 200)

Change History (2)

comment:1 Changed 18 months ago by paulmelnikow

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Summary changed from Exception with dynamic TestCase.urls and settings.APPEND_SLASH=True to Can't use reverse() or is_valid_path() with dynamically set TestCase.urls

This issue also seems to affect reverse() as well as is_valid_path(). To test views which require reverse(), setting APPEND_SLASH=False won't work, so I put the urlconf into the test module instead.

urlpatterns = patterns('',
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
)

class TestLogin(TestCase):
    urls = 'myapp.tests.test_login'

comment:2 Changed 18 months ago by bmispelon

  • Resolution set to invalid
  • Status changed from new to closed

Hi,

The problem is that django.test.TestCase.urls is supposed to be a string pointing to the URLconf module, not a list of patterns.

This is documented there: https://docs.djangoproject.com/en/1.6/topics/testing/tools/#django.test.SimpleTestCase.urls

Though I agree that the documentation is not completely clear, it does say that this attribute should be like settings.ROOT_URLCONF which is itself clearly documented as being a string.

Consequently, I'll close this ticket as invalid.
Feel free to reopen it if, for example, you have suggestions for how to improve the documentation or if you think this should be a new feature.

Thanks.

Note: See TracTickets for help on using tickets.
Back to Top