Methods

reverse(url_name, *args, **kwargs)

When testing views you often find yourself needing to reverse the URL’s name. With django-test-plus there is no need for the from django.core.urlresolvers import reverse boilerplate. Instead just use:

def test_something(self):
    url = self.reverse('my-url-name')
    slug_url = self.reverse('name-takes-a-slug', slug='my-slug')
    pk_url = self.reverse('name-takes-a-pk', pk=12)

As you can see our reverse also passes along any args or kwargs you need to pass in.

get(url_name, follow=False, *args, **kwargs)

Another thing you do often is HTTP get urls. Our get() method assumes you are passing in a named URL with any args or kwargs necessary to reverse the url_name. If needed, place kwargs for TestClient.get() in an ‘extra’ dictionary.:

def test_get_named_url(self):
    response = self.get('my-url-name')
    # Get XML data via AJAX request
    xml_response = self.get(
        'my-url-name',
        extra={'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest'})

When using this get method two other things happen for you: we store the last response in self.last\_response and the response’s Context in self.context. So instead of:

def test_default_django(self):
    response = self.client.get(reverse('my-url-name'))
    self.assertTrue('foo' in response.context)
    self.assertEqual(response.context['foo'], 12)

You can instead write:

def test_testplus_get(self):
    self.get('my-url-name')
    self.assertInContext('foo')
    self.assertEqual(self.context['foo'], 12)

It’s also smart about already reversed URLs so you can be lazy and do:

def test_testplus_get(self):
    url = self.reverse('my-url-name')
    self.get(url)
    self.response_200()

If you need to pass query string parameters to your url name, you can do so like this. Assuming the name ‘search’ maps to ‘/search/’ then:

def test_testplus_get_query(self):
    self.get('search', data={'query': 'testing'})

Would GET /search/?query=testing

post(url_name, follow=False, *args, **kwargs)

Our post() method takes a named URL, an optional dictionary of data you wish to post and any args or kwargs necessary to reverse the url_name. If needed, place kwargs for TestClient.post() in an ‘extra’ dictionary.:

def test_post_named_url(self):
    response = self.post('my-url-name', data={'coolness-factor': 11.0},
                         extra={'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest'})

put(url_name, follow=False, *args, **kwargs)

To support all HTTP methods

patch(url_name, follow=False, *args, **kwargs)

To support all HTTP methods

head(url_name, follow=False, *args, **kwargs)

To support all HTTP methods

trace(url_name, follow=False, *args, **kwargs)

To support all HTTP methods

options(url_name, follow=False, *args, **kwargs)

To support all HTTP methods

delete(url_name, follow=False, *args, **kwargs)

To support all HTTP methods

get_context(key)

Often you need to get things out of the template context, so let’s make that easy:

def test_context_data(self):
    self.get('my-view-with-some-context')
    slug = self.get_context('slug')

assertInContext(key)

You can ensure a specific key exists in the last response’s context by using:

def test_in_context(self):
    self.get('my-view-with-some-context')
    self.assertInContext('some-key')

assertContext(key, value)

We can get context values and ensure they exist, but so let’s also test equality while we’re at it. This asserts that key == value:

def test_in_context(self):
    self.get('my-view-with-some-context')
    self.assertContext('some-key', 'expected value')

response_XXX(response, msg=None) - status code checking

Another test you often need to do is check that a response has a certain HTTP status code. With Django’s default TestCase you would write:

from django.core.urlresolvers import reverse

def test_status(self):
    response = self.client.get(reverse('my-url-name'))
    self.assertEqual(response.status_code, 200)

With django-test-plus you can shorten that to be:

def test_better_status(self):
    response = self.get('my-url-name')
    self.response_200(response)

django-test-plus provides the following response method checks for you:

- response_200()
- response_201()
- response_204()
- response_301()
- response_302()
- response_400()
- response_401()
- response_403()
- response_404()
- response_405()
- response_410()

All of which take an optional Django test client response and a string msg argument that, if specified, is used as the error message when a failure occurs. If it’s available, the response_XXX methods will use the last response. So you can do:

def test_status(self):
    self.get('my-url-name')
    self.response_200()

Which is a bit shorter.

assertResponseContains(text, response=None, html=True)

You often want to check that the last response contains a chunk of HTML. With Django’s default TestCase you would write:

from django.core.urlresolvers import reverse

def test_response_contains(self):
    response = self.client.get(reverse('hello-world'))
    self.assertContains(response, '<p>Hello, World!</p>', html=True)

With django-test-plus you can shorten that to be:

def test_response_contains(self):
    self.get('hello-world')
    self.assertResponseContains('<p>Hello, World!</p>')

assertResponseNotContains(text, response=None, html=True)

The inverse of the above test, make sure the last response does not include the chunk of HTML:

def test_response_not_contains(self):
    self.get('hello-world')
    self.assertResponseNotContains('<p>Hello, Frank!</p>')

assertResponseHeaders(headers, response=None)

Sometimes your views or middleware will set custom headers:

def test_custom_headers(self):
    self.get('my-url-name')
    self.assertResponseHeaders({'X-Custom-Header': 'Foo'})
    self.assertResponseHeaders({'X-Does-Not-Exist': None})

You might also want to check standard headers:

def test_content_type(self):
    self.get('my-json-view')
    self.assertResponseHeaders({'Content-Type': 'application/json'})

get_check_200(url_name, *args, **kwargs)

GETing and checking views return status 200 is so common a test this method makes it even easier:

def test_even_better_status(self):
    response = self.get_check_200('my-url-name')

make_user(username=’testuser’, password=’password’, perms=None)

When testing out views you often need to create various users to ensure all of your logic is safe and sound. To make this process easier, this method will create a user for you:

def test_user_stuff(self)
    user1 = self.make_user('u1')
    user2 = self.make_user('u2')

If creating a User in your project is more complicated, say for example you removed the username field from the default Django Auth model, you can provide a Factory Boy factory to create it or simply override this method on your own sub-class.

To use a Factory Boy factory simply create your class like this:

from test_plus.test import TestCase
from .factories import UserFactory


class MySpecialTest(TestCase):
    user_factory = UserFactory

    def test_special_creation(self):
        user1 = self.make_user('u1')

NOTE: Users created by this method will have their password set to the string ‘password’ by default, in order to ease testing. If you need a specific password simply override the password parameter.

You can also pass in user permissions by passing in a string of ‘<app_name>.<perm name>’ or ‘<app_name>.*’. For example:

user2 = self.make_user(perms=['myapp.create_widget', 'otherapp.*'])