Search code examples
djangounit-testingdjango-urlsdrydjango-tests

Unit testing in Django with flexible url patterns


I was using the following test to check whether page resolves to correct template:

from django.test import TestCase
class HomePageTest(TestCase):
    def test_landing_page_returns_correct_html(self):
        response = self.client.get('/')
        self.assertIn(member='Go to the', container=response.content.decode())

    def test_uses_test_home_template(self):
        response = self.client.get('/test/')
        self.assertTemplateUsed(response=response,
                                template_name='myapp/home.html')

I used many variations of self.client.get('/test/') or self.client.get('/test/dashboard/') etc. in many many tests. All of which are in my myapp.urlpatterns.

Then one day I decided to get rid of /test/. Or simply change the URL pattern. All of the tests failed because, well, I hardcoded the URLs.

I would like to use flexible URL's in my tests. I assume it involves something like:

from myapp.urls import urlpatterns as myapp_urls

and using myapp_urls throughout the tests.

I have two questions:

  1. How can I implement it?
  2. Will there be any (negative) side effects of this approach that I don't foresee?

Solution

  • You can use reverse(), for example if you've got something like this in your urls.py:

    from news import views
    
    urlpatterns = [
        url(r'^archive/$', views.archive, name='news-archive')
    ]
    

    you can write your test like this:

    from django.test import TestCase
    from django.urls import reverse
    
    class NewsArchivePageTest(TestCase):
        def test_news_archive_page_does_something(self):
            response = self.client.get(reverse('news-archive'))
            # do some stuff with the response
    

    Read more about reverse() in the documentation. As for negative side effects I don't think there are any.