I have lots of simple Django views that look like this:
@team_leader_required
def view_all_teams(request):
teams = Team.objects.all()
template_vars = {'toolbar': 'teams',
'teams': teams}
return render(request, "all_teams.html", template_vars)
I end up writing lots of unit tests of the form:
def test_view_all_teams_renders(self):
user = self.create_team_leader()
self.log_in(user)
response = self.client.get(reverse('all_teams'))
self.assertHttp200(response)
Despite my convenience methods for creating users (e.g. .create_team_leader
) and various convenience assertions (e.g. .assertHttp200
), I still end up with a lot of duplication in my tests.
(My tests are simple since I can't see anything else useful to assert about these views -- TestCase.assertTemplateUsed
breaks if you rename templates, even if the view is correct.)
It's easy to miss a test, which gives me little confidence when I rename templates. Is there any way I can automatically generate test cases? Something like (psuedo-code):
for every view in urls:
if view doesn't take extra arguments:
test that view returns 200 when a logged in superuser does a GET
EDIT
Here's a representative snippet from my urls.py:
urlpatterns = patterns('',
url(r'^teams/$', 'teams.views.view_all_teams', name='all_teams'),
url(r'^teams/major/$', 'teams.views.view_major_teams', name='major_teams'),
url(r'^teams/minor/$', 'teams.views.view_minor_teams', name='minor_teams'),
url(r'^teams/(?P<team_id>\d+)/$', 'teams.views.view_team', name='view_team'),
url(r'^teams/(?P<team_id>\d+)/edit$', 'teams.views.edit_team', name='edit_team'),
url(r'^teams/(?P<team_id>\d+)/delete$', 'teams.views.delete_team', name='delete_team'),
I'd like to automatically test the first three views in this list.
from django.core import urlresolvers
from django.test import TestCase
class SimpleTest(TestCase):
def test_simple_views(self):
url_names = [
'all_teams',
'major_teams',
'minor_teams',
'view_team',
'edit_team',
]
user = self.create_team_leader()
self.log_in(user)
for url_name in url_names:
try:
url = urlresolvers.reverse(url_name, args=(), kwargs={})
except urlresolvers.NoReverseMatch:
#print('Pass {}'.format(url_name))
continue
#print('Try {}'.format(url_name))
response = self.client.get(url)
self.assertHttp200(response)
If all url patterns have their name, You can use follow code to define url_names
:
url_names = [p.name for p in teams.urls.urlpatterns]
Known Issues
import unittest
from django.core import urlresolvers
from django.test import TestCase
from teams.urls import urlpatterns
class SimpleTest(TestCase):
...
def setUp(self):
user = self.create_team_leader()
self.log_in(user)
url_names = [p.name for p in urlpatterns]
vs = vars()
def make_test_function(idx, url_name, url):
def t(self):
response = self.client.get(url)
self.assertHttp200(response)
t.__name__ = 'test_' + idx
t.__doc__ = 'simple get test for ' + url_name
return t
for i, url_name in enumerate(url_names):
i = str(i)
try:
url = urlresolvers.reverse(url_name, args=(), kwargs={})
vs['test_' + i] = make_test_function(i, url_name, url)
except urlresolvers.NoReverseMatch as e:
vs['test_' + i] = unittest.skip(url_name + ' requires parameter(s) or view not found')(lambda: 0)
del url_names, vs, make_test_function,
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