django-test-plus provides useful additions to Django's default TestCase
Project description
django-test-plus
Useful additions to Django's default TestCase from REVSYS 3.5, 3.6, 3.7, 3.8, and 3.9.
Supports Django Versions: 2.0, 2.1, 2.2, 3.0, 3.1. and 3.2.
Documentation
Full documentation is available at
Installation
$ pip install django-test-plus
Usage
To use django-test-plus, have your tests inherit from test_plus.test.TestCase rather than the normal django.test.TestCase::
from test_plus.test import TestCase class MyViewTests(TestCase): ...
This is sufficient to get things rolling, but you are encouraged to create your own sub-classes for your projects. This will allow you to add your own project-specific helper methods.
For example, if you have a django project named 'my): ...
This import, which is similar to the way you would import Django's TestCase, is also valid:
from test_plus import TestCase
pytest Usage
You can get a TestCase like object as a pytest fixture now by asking for
tp. All of the methods below would then work in pytest functions. For
example:
def test_url_reverse(tp): expected_url = '/api/' reversed_url = tp.reverse('api') assert expected_url == reversed_url
The
tp_api fixture will provide a
TestCase that uses django-rest-framework's
APIClient():
def test_url_reverse(tp_api): response = tp_api.client.post("myapi", format="json") assert response.status_code == 200
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, 'extra' '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, data, follow=True, *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' we can 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')
assert_http_###_<status_name>(response, msg=None) -.assert_http_200_ok(response)
Django-test-plus provides a majority of the status codes assertions for you. The status assertions
can be found in their own mixin
and should be searchable if you're using an IDE like pycharm. It should be noted that in previous
versions, django-test-plus had assertion methods in the pattern of
response_###(), which are still
available but have since been deprecated. See below for a list of those methods.
Each of the assertion methods takes an optional Django test client
response and a string
msg argument
that, if specified, is used as the error message when a failure occurs. The methods,
assert_http_301_moved_permanently and
assert_http_302_found also take an optional
url argument that
if passed, will check to make sure the
response.url matches.
If it's available, the
assert_http_###_<status_name> methods will use the last response. So you
can do:
def test_status(self): self.get('my-url-name') self.assert_http_200_ok()
Which is a bit shorter.
The
response_###() methods that are deprecated, but still available for use, include:
response_200()
response_201()
response_204()
response_301()
response_302()
response_400()
response_401()
response_403()
response_404()
response_405()
response_409()
response_410()
All of which take an optional Django test client response and a str msg argument that, if specified, is used as the error message when a failure occurs. Just like the
assert_http_###_<status_name>() methods, these methods will use the last response if it's available.
get_check_200(url_name, *args, **kwargs)
GETing and checking views return status 200 is a common test. This method makes it more convenient:: override this method on your own sub-class.
To use a Factory Boy factory, 'password' by default, in order to ease testing.
If you need a specific password, override the
password parameter.
You can also pass in user permissions by passing in a string of
'
<app_name>.<perm name>' or '
)
This method helps you test that a given named URL requires authorization:
def test_auth(self): self.assertLoginRequired('my-restricted-url') self.assertLoginRequired('my-restricted-object', pk=12) self.assertLoginRequired('my-restricted-object', slug='something')
login context
Along with ensuring a view requires login and creating users, the next thing you end up doing is logging in as various users to test your restriction logic: 'password' this number varies due to the nature of your data, with this method you can still test.assert_http_200_ok() an override
of an existing method. Invoking the entire view and the Django request/response
stack is a waste of time when you really want to call the overridden
method directly and test the result.
CBVTestCase to the rescue!
As with TestCase above,().
Development
To work on django-test-plus itself, clone this repository and run the following commands:
$ pip install -r requirements.txt $ pip install -e .
NOTE: You will also need to ensure that the
test_project directory, located
at the root of this repo, is in your virtualenv's path.
Keep in touch!
If you have a question about this project, please open a GitHub issue. If you love us and want to keep track of our goings-on, here's where you can find us online:
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.