Django Test Patterns

July 26, 2010

This post contains some patterns to use when using Django's built in test framework to test a web app.

Testing a Page Fetch

Here's an example of simple successful page fetch

c = Client()
response = c.get('/')
self.assertEquals(response.status_code, 200)

Testing @login_required

To test the login_required decorator, you need to request the page before logging in. This should return a 302 to the login page

response = c.get('/home/')
self.assertEquals(response.status_code, 302)
self.assertEquals(response['Location'], 'http://testserver/accounts/login/?next=/home/')

POST

Here's a test for a POST, passing in parameters and header information:

response = c.post('/guestbook/submit/', {
                                        'name' : 'Joe Bloggs',
                                        'email' : 'drummer@drumcoder.co.uk',
                                        'url' : 'http://www.drumcoder.co.uk/',
                                        'comments' : 'This is to test the guestbook comment system',
                                        },
                                        HTTP_REFERER='http://testserver/guestbook/sign/',
                                        REMOTE_ADDR='127.0.0.1',
                                        HTTP_USER_AGENT='Useragent'
)
self.assertEquals(response.status_code, 302)
self.assertEquals(response['Location'], 'http://testserver/guestbook/thanks/')

POST with Redirect to New Object

I have a POST that returns a URL which contains the ID of a new object. In order to test the response URL we need to get hold of that new id. This can be done by selecting the latest list of objects, ordered by id descending, and then picking off the top object on that list.

response = c.post('/customers/%d/%d/newlicence/' % (lOem.id, lCustomer.id),
                                {'max_users' : '100', 
                                 'max_supervisors' : '20',
                                 'start_date' : '2010-01-01',
                                 'expiry_date' : '2010-12-01', 
                                })
  self.assertEquals(response.status_code, 302)
  lNewLicence = Licence.objects.all().order_by('-id')[0]
  self.assertEquals(response['Location'], 'http://testserver/customers/%d/%d/%d/' % (lOem.id, lCustomer.id, lNewLicence.id))

Login

To login using the test client, use the following:

if c.login(username='drumcoder', password='secret') == False:
  self.fail("Can't login")

Passing Headers

Sometimes a test requires a header, such as HTTP_USER_AGENT to be present. This can be done using the following:

response = c.get('/home/', **{'HTTP_USER_AGENT':'silly-human', 'REMOTE_ADDR':'127.0.0.1'})
self.assertEquals(response.status_code, 302)
self.assertEquals(response['Location'], 'http://testserver/customers/')

Tags: django test