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/')