How do I unit test django urls?

DjangoUnit TestingTddDjango Urls

Django Problem Overview


I have achieved 100% test coverage in my application everywhere except my urls.py. Do you have any recommendations for how I could write meaningful unit tests for my URLs?

FWIW This question has arisen as I am experimenting with Test-Driven Development and want failing tests before I write code to fix them.

Django Solutions


Solution 1 - Django

One way would be to reverse URL names and validate

Example

urlpatterns = [
    url(r'^archive/(\d{4})/$', archive, name="archive"),
    url(r'^archive-summary/(\d{4})/$', archive, name="archive-summary"),
]

Now, in the test

from django.urls import reverse

url = reverse('archive', args=[1988])
assertEqual(url, '/archive/1988/')

url = reverse('archive-summary', args=[1988])
assertEqual(url, '/archive-summary/1988/')

You are probably testing the views anyways.

Now, to test that the URL connect to the right view, you could use resolve

from django.urls import resolve

resolver = resolve('/summary/')
assertEqual(resolver.view_name, 'summary')

Now in the variable resolver (ResolverMatch class instance), you have the following options

 'app_name',
 'app_names',
 'args',
 'func',
 'kwargs',
 'namespace',
 'namespaces',
 'url_name',
 'view_name'

Solution 2 - Django

Just complementing the answer from @karthikr (on the basis of his)

-> you may assert that the view in charge of resolve is the one you'd expect using resolver.func.cls

example

from unittest import TestCase
from django.urls import resolve

from foo.api.v1.views import FooView


class TestUrls(TestCase):
    def test_resolution_for_foo(self):
        resolver = resolve('/api/v1/foo')
        self.assertEqual(resolver.func.cls, FooView)

Solution 3 - Django

Sorry for beeing a miner but I found this place as a first under key words "django url testing".

I fairly agree with my predecessors but I am also sure there is a better way to test your URLs. The main reason why we should not use "resolver = resolve('url/path')" is that the paths are of some kind fluent when the view's names are more fixed.

Well in simple words, this is better:

class TestUrls(TestCase):

    def test_foo_url_resolves(self):
        url = reverse('bar:foo')
        self.assertEqual(resolve(url).func.view_class, FooBarView)

'bar:foo' - bar is a namespace and foo is a view name

than this

class TestUrls(TestCase):
    def test_resolution_for_foo(self):
        resolver = resolve('/api/v1/foo')
        self.assertEqual(resolver.func.cls, FooView)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionmeshyView Question on Stackoverflow
Solution 1 - DjangokarthikrView Answer on Stackoverflow
Solution 2 - DjangoManu ArteroView Answer on Stackoverflow
Solution 3 - DjangoSerSergiousView Answer on Stackoverflow