summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Graham <timograham@gmail.com>2013-12-31 06:24:11 -0500
committerTim Graham <timograham@gmail.com>2013-12-31 08:14:09 -0500
commit9953e98e6ad9298869cd12e20bd3c05c0d19fa10 (patch)
tree5b75046da650e7aad0ebf588435994952cae4032
parenta95f74e7078e2f38935e3de5e3229b8ff585ae00 (diff)
Fixed #21701 -- Improved testing doc titles and added testing/tools.txt.
Thanks cjerdonek for the suggestion.
-rw-r--r--docs/internals/contributing/writing-code/unit-tests.txt4
-rw-r--r--docs/intro/contributing.txt2
-rw-r--r--docs/topics/email.txt5
-rw-r--r--docs/topics/testing/index.txt16
-rw-r--r--docs/topics/testing/overview.txt1605
-rw-r--r--docs/topics/testing/tools.txt1596
6 files changed, 1614 insertions, 1614 deletions
diff --git a/docs/internals/contributing/writing-code/unit-tests.txt b/docs/internals/contributing/writing-code/unit-tests.txt
index d6a031b3ae..36f767614a 100644
--- a/docs/internals/contributing/writing-code/unit-tests.txt
+++ b/docs/internals/contributing/writing-code/unit-tests.txt
@@ -13,8 +13,8 @@ The tests cover:
We appreciate any and all contributions to the test suite!
The Django tests all use the testing infrastructure that ships with Django for
-testing applications. See :doc:`Testing Django applications
-</topics/testing/overview>` for an explanation of how to write new tests.
+testing applications. See :doc:`/topics/testing/overview` for an explanation of
+how to write new tests.
.. _running-unit-tests:
diff --git a/docs/intro/contributing.txt b/docs/intro/contributing.txt
index 8a16a9b0d0..7250f9e676 100644
--- a/docs/intro/contributing.txt
+++ b/docs/intro/contributing.txt
@@ -281,7 +281,7 @@ correctly in a couple different situations.
computer programming, so there's lots of information out there:
* A good first look at writing tests for Django can be found in the
- documentation on :doc:`Testing Django applications </topics/testing/overview>`.
+ documentation on :doc:`/topics/testing/overview`.
* Dive Into Python (a free online book for beginning Python developers)
includes a great `introduction to Unit Testing`__.
* After reading those, if you want something a little meatier to sink
diff --git a/docs/topics/email.txt b/docs/topics/email.txt
index 058a007721..6b93d7d2b8 100644
--- a/docs/topics/email.txt
+++ b/docs/topics/email.txt
@@ -629,6 +629,5 @@ the email body. You then only need to set the :setting:`EMAIL_HOST` and
:setting:`EMAIL_PORT` accordingly. For a more detailed discussion of SMTP
server options, see the Python documentation for the :mod:`smtpd` module.
-For information about unit-testing the sending of emails in your
-application, see the :ref:`topics-testing-email` section of :doc:`Testing
-Django applications </topics/testing/overview>`.
+For information about unit-testing the sending of emails in your application,
+see the :ref:`topics-testing-email` section of the testing documentation.
diff --git a/docs/topics/testing/index.txt b/docs/topics/testing/index.txt
index 1a99a399b4..e8cab96277 100644
--- a/docs/topics/testing/index.txt
+++ b/docs/topics/testing/index.txt
@@ -2,12 +2,6 @@
Testing in Django
=================
-.. toctree::
- :hidden:
-
- overview
- advanced
-
Automated testing is an extremely useful bug-killing tool for the modern
Web developer. You can use a collection of tests -- a **test suite** -- to
solve, or avoid, a number of problems:
@@ -28,9 +22,6 @@ it should be doing.
The best part is, it's really easy.
-Where to go from here
-=====================
-
The preferred way to write tests in Django is using the :mod:`unittest` module
built in to the Python standard library. This is covered in detail in the
:doc:`overview` document.
@@ -38,3 +29,10 @@ built in to the Python standard library. This is covered in detail in the
You can also use any *other* Python test framework; Django provides an API and
tools for that kind of integration. They are described in the
:ref:`other-testing-frameworks` section of :doc:`advanced`.
+
+.. toctree::
+ :maxdepth: 1
+
+ overview
+ tools
+ advanced
diff --git a/docs/topics/testing/overview.txt b/docs/topics/testing/overview.txt
index 3bdb13c28f..078c2a1da9 100644
--- a/docs/topics/testing/overview.txt
+++ b/docs/topics/testing/overview.txt
@@ -1,14 +1,15 @@
-===========================
-Testing Django applications
-===========================
+=========================
+Writing and running tests
+=========================
.. module:: django.test
:synopsis: Testing tools for Django applications.
.. seealso::
- The :doc:`testing tutorial </intro/tutorial05>` and the
- :doc:`advanced testing topics </topics/testing/advanced>`.
+ The :doc:`testing tutorial </intro/tutorial05>`, the :doc:`testing tools
+ reference </topics/testing/tools>`, and the :doc:`advanced testing topics
+ </topics/testing/advanced>`.
This document is split into two primary sections. First, we explain how to write
tests with Django. Then, we explain how to run them.
@@ -302,1597 +303,3 @@ to a faster hashing algorithm::
Don't forget to also include in :setting:`PASSWORD_HASHERS` any hashing
algorithm used in fixtures, if any.
-
-Testing tools
-=============
-
-Django provides a small set of tools that come in handy when writing tests.
-
-.. _test-client:
-
-The test client
----------------
-
-The test client is a Python class that acts as a dummy Web browser, allowing
-you to test your views and interact with your Django-powered application
-programmatically.
-
-Some of the things you can do with the test client are:
-
-* Simulate GET and POST requests on a URL and observe the response --
- everything from low-level HTTP (result headers and status codes) to
- page content.
-
-* See the chain of redirects (if any) and check the URL and status code at
- each step.
-
-* Test that a given request is rendered by a given Django template, with
- a template context that contains certain values.
-
-Note that the test client is not intended to be a replacement for Selenium_ or
-other "in-browser" frameworks. Django's test client has a different focus. In
-short:
-
-* Use Django's test client to establish that the correct template is being
- rendered and that the template is passed the correct context data.
-
-* Use in-browser frameworks like Selenium_ to test *rendered* HTML and the
- *behavior* of Web pages, namely JavaScript functionality. Django also
- provides special support for those frameworks; see the section on
- :class:`~django.test.LiveServerTestCase` for more details.
-
-A comprehensive test suite should use a combination of both test types.
-
-Overview and a quick example
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-To use the test client, instantiate ``django.test.Client`` and retrieve
-Web pages::
-
- >>> from django.test import Client
- >>> c = Client()
- >>> response = c.post('/login/', {'username': 'john', 'password': 'smith'})
- >>> response.status_code
- 200
- >>> response = c.get('/customer/details/')
- >>> response.content
- '<!DOCTYPE html...'
-
-As this example suggests, you can instantiate ``Client`` from within a session
-of the Python interactive interpreter.
-
-Note a few important things about how the test client works:
-
-* The test client does *not* require the Web server to be running. In fact,
- it will run just fine with no Web server running at all! That's because
- it avoids the overhead of HTTP and deals directly with the Django
- framework. This helps make the unit tests run quickly.
-
-* When retrieving pages, remember to specify the *path* of the URL, not the
- whole domain. For example, this is correct::
-
- >>> c.get('/login/')
-
- This is incorrect::
-
- >>> c.get('http://www.example.com/login/')
-
- The test client is not capable of retrieving Web pages that are not
- powered by your Django project. If you need to retrieve other Web pages,
- use a Python standard library module such as :mod:`urllib` or
- :mod:`urllib2`.
-
-* To resolve URLs, the test client uses whatever URLconf is pointed-to by
- your :setting:`ROOT_URLCONF` setting.
-
-* Although the above example would work in the Python interactive
- interpreter, some of the test client's functionality, notably the
- template-related functionality, is only available *while tests are
- running*.
-
- The reason for this is that Django's test runner performs a bit of black
- magic in order to determine which template was loaded by a given view.
- This black magic (essentially a patching of Django's template system in
- memory) only happens during test running.
-
-* By default, the test client will disable any CSRF checks
- performed by your site.
-
- If, for some reason, you *want* the test client to perform CSRF
- checks, you can create an instance of the test client that
- enforces CSRF checks. To do this, pass in the
- ``enforce_csrf_checks`` argument when you construct your
- client::
-
- >>> from django.test import Client
- >>> csrf_client = Client(enforce_csrf_checks=True)
-
-Making requests
-~~~~~~~~~~~~~~~
-
-Use the ``django.test.Client`` class to make requests.
-
-.. class:: Client(enforce_csrf_checks=False, **defaults)
-
- It requires no arguments at time of construction. However, you can use
- keywords arguments to specify some default headers. For example, this will
- send a ``User-Agent`` HTTP header in each request::
-
- >>> c = Client(HTTP_USER_AGENT='Mozilla/5.0')
-
- The values from the ``extra`` keywords arguments passed to
- :meth:`~django.test.Client.get()`,
- :meth:`~django.test.Client.post()`, etc. have precedence over
- the defaults passed to the class constructor.
-
- The ``enforce_csrf_checks`` argument can be used to test CSRF
- protection (see above).
-
- Once you have a ``Client`` instance, you can call any of the following
- methods:
-
- .. method:: Client.get(path, data={}, follow=False, secure=False, **extra)
-
- .. versionadded:: 1.7
-
- The ``secure`` argument was added.
-
- Makes a GET request on the provided ``path`` and returns a ``Response``
- object, which is documented below.
-
- The key-value pairs in the ``data`` dictionary are used to create a GET
- data payload. For example::
-
- >>> c = Client()
- >>> c.get('/customers/details/', {'name': 'fred', 'age': 7})
-
- ...will result in the evaluation of a GET request equivalent to::
-
- /customers/details/?name=fred&age=7
-
- The ``extra`` keyword arguments parameter can be used to specify
- headers to be sent in the request. For example::
-
- >>> c = Client()
- >>> c.get('/customers/details/', {'name': 'fred', 'age': 7},
- ... HTTP_X_REQUESTED_WITH='XMLHttpRequest')
-
- ...will send the HTTP header ``HTTP_X_REQUESTED_WITH`` to the
- details view, which is a good way to test code paths that use the
- :meth:`django.http.HttpRequest.is_ajax()` method.
-
- .. admonition:: CGI specification
-
- The headers sent via ``**extra`` should follow CGI_ specification.
- For example, emulating a different "Host" header as sent in the
- HTTP request from the browser to the server should be passed
- as ``HTTP_HOST``.
-
- .. _CGI: http://www.w3.org/CGI/
-
- If you already have the GET arguments in URL-encoded form, you can
- use that encoding instead of using the data argument. For example,
- the previous GET request could also be posed as::
-
- >>> c = Client()
- >>> c.get('/customers/details/?name=fred&age=7')
-
- If you provide a URL with both an encoded GET data and a data argument,
- the data argument will take precedence.
-
- If you set ``follow`` to ``True`` the client will follow any redirects
- and a ``redirect_chain`` attribute will be set in the response object
- containing tuples of the intermediate urls and status codes.
-
- If you had a URL ``/redirect_me/`` that redirected to ``/next/``, that
- redirected to ``/final/``, this is what you'd see::
-
- >>> response = c.get('/redirect_me/', follow=True)
- >>> response.redirect_chain
- [(u'http://testserver/next/', 302), (u'http://testserver/final/', 302)]
-
- If you set ``secure`` to ``True`` the client will emulate an HTTPS
- request.
-
- .. method:: Client.post(path, data={}, content_type=MULTIPART_CONTENT, follow=False, secure=False, **extra)
-
- Makes a POST request on the provided ``path`` and returns a
- ``Response`` object, which is documented below.
-
- The key-value pairs in the ``data`` dictionary are used to submit POST
- data. For example::
-
- >>> c = Client()
- >>> c.post('/login/', {'name': 'fred', 'passwd': 'secret'})
-
- ...will result in the evaluation of a POST request to this URL::
-
- /login/
-
- ...with this POST data::
-
- name=fred&passwd=secret
-
- If you provide ``content_type`` (e.g. :mimetype:`text/xml` for an XML
- payload), the contents of ``data`` will be sent as-is in the POST
- request, using ``content_type`` in the HTTP ``Content-Type`` header.
-
- If you don't provide a value for ``content_type``, the values in
- ``data`` will be transmitted with a content type of
- :mimetype:`multipart/form-data`. In this case, the key-value pairs in
- ``data`` will be encoded as a multipart message and used to create the
- POST data payload.
-
- To submit multiple values for a given key -- for example, to specify
- the selections for a ``<select multiple>`` -- provide the values as a
- list or tuple for the required key. For example, this value of ``data``
- would submit three selected values for the field named ``choices``::
-
- {'choices': ('a', 'b', 'd')}
-
- Submitting files is a special case. To POST a file, you need only
- provide the file field name as a key, and a file handle to the file you
- wish to upload as a value. For example::
-
- >>> c = Client()
- >>> with open('wishlist.doc') as fp:
- ... c.post('/customers/wishes/', {'name': 'fred', 'attachment': fp})
-
- (The name ``attachment`` here is not relevant; use whatever name your
- file-processing code expects.)
-
- Note that if you wish to use the same file handle for multiple
- ``post()`` calls then you will need to manually reset the file
- pointer between posts. The easiest way to do this is to
- manually close the file after it has been provided to
- ``post()``, as demonstrated above.
-
- You should also ensure that the file is opened in a way that
- allows the data to be read. If your file contains binary data
- such as an image, this means you will need to open the file in
- ``rb`` (read binary) mode.
-
- The ``extra`` argument acts the same as for :meth:`Client.get`.
-
- If the URL you request with a POST contains encoded parameters, these
- parameters will be made available in the request.GET data. For example,
- if you were to make the request::
-
- >>> c.post('/login/?visitor=true', {'name': 'fred', 'passwd': 'secret'})
-
- ... the view handling this request could interrogate request.POST
- to retrieve the username and password, and could interrogate request.GET
- to determine if the user was a visitor.
-
- If you set ``follow`` to ``True`` the client will follow any redirects
- and a ``redirect_chain`` attribute will be set in the response object
- containing tuples of the intermediate urls and status codes.
-
- If you set ``secure`` to ``True`` the client will emulate an HTTPS
- request.
-
- .. method:: Client.head(path, data={}, follow=False, secure=False, **extra)
-
- Makes a HEAD request on the provided ``path`` and returns a
- ``Response`` object. This method works just like :meth:`Client.get`,
- including the ``follow``, ``secure`` and ``extra`` arguments, except
- it does not return a message body.
-
- .. method:: Client.options(path, data='', content_type='application/octet-stream', follow=False, secure=False, **extra)
-
- Makes an OPTIONS request on the provided ``path`` and returns a
- ``Response`` object. Useful for testing RESTful interfaces.
-
- When ``data`` is provided, it is used as the request body, and
- a ``Content-Type`` header is set to ``content_type``.
-
- The ``follow``, ``secure`` and ``extra`` arguments act the same as for
- :meth:`Client.get`.
-
- .. method:: Client.put(path, data='', content_type='application/octet-stream', follow=False, secure=False, **extra)
-
- Makes a PUT request on the provided ``path`` and returns a
- ``Response`` object. Useful for testing RESTful interfaces.
-
- When ``data`` is provided, it is used as the request body, and
- a ``Content-Type`` header is set to ``content_type``.
-
- The ``follow``, ``secure`` and ``extra`` arguments act the same as for
- :meth:`Client.get`.
-
- .. method:: Client.patch(path, data='', content_type='application/octet-stream', follow=False, secure=False, **extra)
-
- Makes a PATCH request on the provided ``path`` and returns a
- ``Response`` object. Useful for testing RESTful interfaces.
-
- The ``follow``, ``secure`` and ``extra`` arguments act the same as for
- :meth:`Client.get`.
-
- .. method:: Client.delete(path, data='', content_type='application/octet-stream', follow=False, secure=False, **extra)
-
- Makes an DELETE request on the provided ``path`` and returns a
- ``Response`` object. Useful for testing RESTful interfaces.
-
- When ``data`` is provided, it is used as the request body, and
- a ``Content-Type`` header is set to ``content_type``.
-
- The ``follow``, ``secure`` and ``extra`` arguments act the same as for
- :meth:`Client.get`.
-
- .. method:: Client.login(**credentials)
-
- If your site uses Django's :doc:`authentication system</topics/auth/index>`
- and you deal with logging in users, you can use the test client's
- ``login()`` method to simulate the effect of a user logging into the
- site.
-
- After you call this method, the test client will have all the cookies
- and session data required to pass any login-based tests that may form
- part of a view.
-
- The format of the ``credentials`` argument depends on which
- :ref:`authentication backend <authentication-backends>` you're using
- (which is configured by your :setting:`AUTHENTICATION_BACKENDS`
- setting). If you're using the standard authentication backend provided
- by Django (``ModelBackend``), ``credentials`` should be the user's
- username and password, provided as keyword arguments::
-
- >>> c = Client()
- >>> c.login(username='fred', password='secret')
-
- # Now you can access a view that's only available to logged-in users.
-
- If you're using a different authentication backend, this method may
- require different credentials. It requires whichever credentials are
- required by your backend's ``authenticate()`` method.
-
- ``login()`` returns ``True`` if it the credentials were accepted and
- login was successful.
-
- Finally, you'll need to remember to create user accounts before you can
- use this method. As we explained above, the test runner is executed
- using a test database, which contains no users by default. As a result,
- user accounts that are valid on your production site will not work
- under test conditions. You'll need to create users as part of the test
- suite -- either manually (using the Django model API) or with a test
- fixture. Remember that if you want your test user to have a password,
- you can't set the user's password by setting the password attribute
- directly -- you must use the
- :meth:`~django.contrib.auth.models.User.set_password()` function to
- store a correctly hashed password. Alternatively, you can use the
- :meth:`~django.contrib.auth.models.UserManager.create_user` helper
- method to create a new user with a correctly hashed password.
-
- .. versionadded:: 1.7
-
- Requests made with :meth:`~django.test.Client.login` go through the
- request middleware. If you need to control the environment, you can
- do so at :class:`~django.test.Client` instantiation or with the
- `Client.defaults` attribute.
-
- .. method:: Client.logout()
-
- If your site uses Django's :doc:`authentication system</topics/auth/index>`,
- the ``logout()`` method can be used to simulate the effect of a user
- logging out of your site.
-
- After you call this method, the test client will have all the cookies
- and session data cleared to defaults. Subsequent requests will appear
- to come from an :class:`~django.contrib.auth.models.AnonymousUser`.
-
- .. versionadded:: 1.7
-
- Requests made with :meth:`~django.test.Client.logout` go through the
- request middleware. If you need to control the environment, you can
- do so at :class:`~django.test.Client` instantiation or with the
- `Client.defaults` attribute.
-
-Testing responses
-~~~~~~~~~~~~~~~~~
-
-The ``get()`` and ``post()`` methods both return a ``Response`` object. This
-``Response`` object is *not* the same as the ``HttpResponse`` object returned
-Django views; the test response object has some additional data useful for
-test code to verify.
-
-Specifically, a ``Response`` object has the following attributes:
-
-.. class:: Response()
-
- .. attribute:: client
-
- The test client that was used to make the request that resulted in the
- response.
-
- .. attribute:: content
-
- The body of the response, as a string. This is the final page content as
- rendered by the view, or any error message.
-
- .. attribute:: context
-
- The template ``Context`` instance that was used to render the template that
- produced the response content.
-
- If the rendered page used multiple templates, then ``context`` will be a
- list of ``Context`` objects, in the order in which they were rendered.
-
- Regardless of the number of templates used during rendering, you can
- retrieve context values using the ``[]`` operator. For example, the
- context variable ``name`` could be retrieved using::
-
- >>> response = client.get('/foo/')
- >>> response.context['name']
- 'Arthur'
-
- .. attribute:: request
-
- The request data that stimulated the response.
-
- .. attribute:: status_code
-
- The HTTP status of the response, as an integer. See
- :rfc:`2616#section-10` for a full list of HTTP status codes.
-
- .. attribute:: templates
-
- A list of ``Template`` instances used to render the final content, in
- the order they were rendered. For each template in the list, use
- ``template.name`` to get the template's file name, if the template was
- loaded from a file. (The name is a string such as
- ``'admin/index.html'``.)
-
-You can also use dictionary syntax on the response object to query the value
-of any settings in the HTTP headers. For example, you could determine the
-content type of a response using ``response['Content-Type']``.
-
-Exceptions
-~~~~~~~~~~
-
-If you point the test client at a view that raises an exception, that exception
-will be visible in the test case. You can then use a standard ``try ... except``
-block or :meth:`~unittest.TestCase.assertRaises` to test for exceptions.
-
-The only exceptions that are not visible to the test client are ``Http404``,
-``PermissionDenied`` and ``SystemExit``. Django catches these exceptions
-internally and converts them into the appropriate HTTP response codes. In these
-cases, you can check ``response.status_code`` in your test.
-
-Persistent state
-~~~~~~~~~~~~~~~~
-
-The test client is stateful. If a response returns a cookie, then that cookie
-will be stored in the test client and sent with all subsequent ``get()`` and
-``post()`` requests.
-
-Expiration policies for these cookies are not followed. If you want a cookie
-to expire, either delete it manually or create a new ``Client`` instance (which
-will effectively delete all cookies).
-
-A test client has two attributes that store persistent state information. You
-can access these properties as part of a test condition.
-
-.. attribute:: Client.cookies
-
- A Python :class:`~Cookie.SimpleCookie` object, containing the current values
- of all the client cookies. See the documentation of the :mod:`Cookie` module
- for more.
-
-.. attribute:: Client.session
-
- A dictionary-like object containing session information. See the
- :doc:`session documentation</topics/http/sessions>` for full details.
-
- To modify the session and then save it, it must be stored in a variable
- first (because a new ``SessionStore`` is created every time this property
- is accessed)::
-
- def test_something(self):
- session = self.client.session
- session['somekey'] = 'test'
- session.save()
-
-Example
-~~~~~~~
-
-The following is a simple unit test using the test client::
-
- import unittest
- from django.test import Client
-
- class SimpleTest(unittest.TestCase):
- def setUp(self):
- # Every test needs a client.
- self.client = Client()
-
- def test_details(self):
- # Issue a GET request.
- response = self.client.get('/customer/details/')
-
- # Check that the response is 200 OK.
- self.assertEqual(response.status_code, 200)
-
- # Check that the rendered context contains 5 customers.
- self.assertEqual(len(response.context['customers']), 5)
-
-.. seealso::
-
- :class:`django.test.RequestFactory`
-
-.. _django-testcase-subclasses:
-
-Provided test case classes
---------------------------
-
-Normal Python unit test classes extend a base class of
-:class:`unittest.TestCase`. Django provides a few extensions of this base class:
-
-.. _testcase_hierarchy_diagram:
-
-.. figure:: _images/django_unittest_classes_hierarchy.*
- :alt: Hierarchy of Django unit testing classes (TestCase subclasses)
- :width: 508
- :height: 328
-
- Hierarchy of Django unit testing classes
-
-SimpleTestCase
-~~~~~~~~~~~~~~
-
-.. class:: SimpleTestCase()
-
-A thin subclass of :class:`unittest.TestCase`, it extends it with some basic
-functionality like:
-
-* Saving and restoring the Python warning machinery state.
-* Some useful assertions like:
-
- * Checking that a callable :meth:`raises a certain exception
- <SimpleTestCase.assertRaisesMessage>`.
- * Testing form field :meth:`rendering and error treatment
- <SimpleTestCase.assertFieldOutput>`.
- * Testing :meth:`HTML responses for the presence/lack of a given fragment
- <SimpleTestCase.assertContains>`.
- * Verifying that a template :meth:`has/hasn't been used to generate a given
- response content <SimpleTestCase.assertTemplateUsed>`.
- * Verifying a HTTP :meth:`redirect <SimpleTestCase.assertRedirects>` is
- performed by the app.
- * Robustly testing two :meth:`HTML fragments <SimpleTestCase.assertHTMLEqual>`
- for equality/inequality or :meth:`containment <SimpleTestCase.assertInHTML>`.
- * Robustly testing two :meth:`XML fragments <SimpleTestCase.assertXMLEqual>`
- for equality/inequality.
- * Robustly testing two :meth:`JSON fragments <SimpleTestCase.assertJSONEqual>`
- for equality.
-
-* The ability to run tests with :ref:`modified settings <overriding-settings>`.
-* Using the :attr:`~SimpleTestCase.client` :class:`~django.test.Client`.
-* Custom test-time :attr:`URL maps <SimpleTestCase.urls>`.
-
-.. versionchanged:: 1.6
-
- The latter two features were moved from ``TransactionTestCase`` to
- ``SimpleTestCase`` in Django 1.6.
-
-If you need any of the other more complex and heavyweight Django-specific
-features like:
-
-* Testing or using the ORM.
-* Database :attr:`~TransactionTestCase.fixtures`.
-* Test :ref:`skipping based on database backend features <skipping-tests>`.
-* The remaining specialized :meth:`assert*
- <TransactionTestCase.assertQuerysetEqual>` methods.
-
-then you should use :class:`~django.test.TransactionTestCase` or
-:class:`~django.test.TestCase` instead.
-
-``SimpleTestCase`` inherits from ``unittest.TestCase``.
-
-TransactionTestCase
-~~~~~~~~~~~~~~~~~~~
-
-.. class:: TransactionTestCase()
-
-Django's ``TestCase`` class (described below) makes use of database transaction
-facilities to speed up the process of resetting the database to a known state
-at the beginning of each test. A consequence of this, however, is that the
-effects of transaction commit and rollback cannot be tested by a Django
-``TestCase`` class. If your test requires testing of such transactional
-behavior, you should use a Django ``TransactionTestCase``.
-
-``TransactionTestCase`` and ``TestCase`` are identical except for the manner
-in which the database is reset to a known state and the ability for test code
-to test the effects of commit and rollback:
-
-* A ``TransactionTestCase`` resets the database after the test runs by
- truncating all tables. A ``TransactionTestCase`` may call commit and rollback
- and observe the effects of these calls on the database.
-
-* A ``TestCase``, on the other hand, does not truncate tables after a test.
- Instead, it encloses the test code in a database transaction that is rolled
- back at the end of the test. Both explicit commits like
- ``transaction.commit()`` and implicit ones that may be caused by
- ``transaction.atomic()`` are replaced with a ``nop`` operation. This
- guarantees that the rollback at the end of the test restores the database to
- its initial state.
-
- When running on a database that does not support rollback (e.g. MySQL with the
- MyISAM storage engine), ``TestCase`` falls back to initializing the database
- by truncating tables and reloading initial data.
-
-.. warning::
-
- While ``commit`` and ``rollback`` operations still *appear* to work when
- used in ``TestCase``, no actual commit or rollback will be performed by the
- database. This can cause your tests to pass or fail unexpectedly. Always
- use ``TransactionTestCase`` when testing transactional behavior.
-
-``TransactionTestCase`` inherits from :class:`~django.test.SimpleTestCase`.
-
-TestCase
-~~~~~~~~
-
-.. class:: TestCase()
-
-This class provides some additional capabilities that can be useful for testing
-Web sites.
-
-Converting a normal :class:`unittest.TestCase` to a Django :class:`TestCase` is
-easy: Just change the base class of your test from ``'unittest.TestCase'`` to
-``'django.test.TestCase'``. All of the standard Python unit test functionality
-will continue to be available, but it will be augmented with some useful
-additions, including:
-
-* Automatic loading of fixtures.
-
-* Wraps each test in a transaction.
-
-* Creates a TestClient instance.
-
-* Django-specific assertions for testing for things like redirection and form
- errors.
-
-``TestCase`` inherits from :class:`~django.test.TransactionTestCase`.
-
-.. _live-test-server:
-
-LiveServerTestCase
-~~~~~~~~~~~~~~~~~~
-
-.. class:: LiveServerTestCase()
-
-``LiveServerTestCase`` does basically the same as
-:class:`~django.test.TransactionTestCase` with one extra feature: it launches a
-live Django server in the background on setup, and shuts it down on teardown.
-This allows the use of automated test clients other than the
-:ref:`Django dummy client <test-client>` such as, for example, the Selenium_
-client, to execute a series of functional tests inside a browser and simulate a
-real user's actions.
-
-By default the live server's address is ``'localhost:8081'`` and the full URL
-can be accessed during the tests with ``self.live_server_url``. If you'd like
-to change the default address (in the case, for example, where the 8081 port is
-already taken) then you may pass a different one to the :djadmin:`test` command
-via the :djadminopt:`--liveserver` option, for example:
-
-.. code-block:: bash
-
- ./manage.py test --liveserver=localhost:8082
-
-Another way of changing the default server address is by setting the
-`DJANGO_LIVE_TEST_SERVER_ADDRESS` environment variable somewhere in your
-code (for example, in a :ref:`custom test runner<topics-testing-test_runner>`):
-
-.. code-block:: python
-
- import os
- os.environ['DJANGO_LIVE_TEST_SERVER_ADDRESS'] = 'localhost:8082'
-
-In the case where the tests are run by multiple processes in parallel (for
-example, in the context of several simultaneous `continuous integration`_
-builds), the processes will compete for the same address, and therefore your
-tests might randomly fail with an "Address already in use" error. To avoid this
-problem, you can pass a comma-separated list of ports or ranges of ports (at
-least as many as the number of potential parallel processes). For example:
-
-.. code-block:: bash
-
- ./manage.py test --liveserver=localhost:8082,8090-8100,9000-9200,7041
-
-Then, during test execution, each new live test server will try every specified
-port until it finds one that is free and takes it.
-
-.. _continuous integration: http://en.wikipedia.org/wiki/Continuous_integration
-
-To demonstrate how to use ``LiveServerTestCase``, let's write a simple Selenium
-test. First of all, you need to install the `selenium package`_ into your
-Python path:
-
-.. code-block:: bash
-
- pip install selenium
-
-Then, add a ``LiveServerTestCase``-based test to your app's tests module
-(for example: ``myapp/tests.py``). The code for this test may look as follows:
-
-.. code-block:: python
-
- from django.test import LiveServerTestCase
- from selenium.webdriver.firefox.webdriver import WebDriver
-
- class MySeleniumTests(LiveServerTestCase):
- fixtures = ['user-data.json']
-
- @classmethod
- def setUpClass(cls):
- cls.selenium = WebDriver()
- super(MySeleniumTests, cls).setUpClass()
-
- @classmethod
- def tearDownClass(cls):
- cls.selenium.quit()
- super(MySeleniumTests, cls).tearDownClass()
-
- def test_login(self):
- self.selenium.get('%s%s' % (self.live_server_url, '/login/'))
- username_input = self.selenium.find_element_by_name("username")
- username_input.send_keys('myuser')
- password_input = self.selenium.find_element_by_name("password")
- password_input.send_keys('secret')
- self.selenium.find_element_by_xpath('//input[@value="Log in"]').click()
-
-Finally, you may run the test as follows:
-
-.. code-block:: bash
-
- ./manage.py test myapp.MySeleniumTests.test_login
-
-This example will automatically open Firefox then go to the login page, enter
-the credentials and press the "Log in" button. Selenium offers other drivers in
-case you do not have Firefox installed or wish to use another browser. The
-example above is just a tiny fraction of what the Selenium client can do; check
-out the `full reference`_ for more details.
-
-.. _Selenium: http://seleniumhq.org/
-.. _selenium package: https://pypi.python.org/pypi/selenium
-.. _full reference: http://selenium-python.readthedocs.org/en/latest/api.html
-.. _Firefox: http://www.mozilla.com/firefox/
-
-.. versionchanged:: 1.7
-
- Before Django 1.7 ``LiveServerTestCase`` used to rely on the
- :doc:`staticfiles contrib app </howto/static-files/index>` to get the
- static assets of the application(s) under test transparently served at their
- expected locations during the execution of these tests.
-
- In Django 1.7 this dependency of core functionality on a ``contrib``
- appplication has been removed, because of which ``LiveServerTestCase``
- ability in this respect has been retrofitted to simply publish the contents
- of the file system under :setting:`STATIC_ROOT` at the :setting:`STATIC_URL`
- URL.
-
- If you use the ``staticfiles`` app in your project and need to perform live
- testing then you might want to consider using the
- :class:`~django.contrib.staticfiles.testing.StaticLiveServerCase` subclass
- shipped with it instead because it's the one that implements the original
- behavior now. See :ref:`the relevant documentation
- <staticfiles-testing-support>` for more details.
-
-.. note::
-
- When using an in-memory SQLite database to run the tests, the same database
- connection will be shared by two threads in parallel: the thread in which
- the live server is run and the thread in which the test case is run. It's
- important to prevent simultaneous database queries via this shared
- connection by the two threads, as that may sometimes randomly cause the
- tests to fail. So you need to ensure that the two threads don't access the
- database at the same time. In particular, this means that in some cases
- (for example, just after clicking a link or submitting a form), you might
- need to check that a response is received by Selenium and that the next
- page is loaded before proceeding with further test execution.
- Do this, for example, by making Selenium wait until the ``<body>`` HTML tag
- is found in the response (requires Selenium > 2.13):
-
- .. code-block:: python
-
- def test_login(self):
- from selenium.webdriver.support.wait import WebDriverWait
- timeout = 2
- ...
- self.selenium.find_element_by_xpath('//input[@value="Log in"]').click()
- # Wait until the response is received
- WebDriverWait(self.selenium, timeout).until(
- lambda driver: driver.find_element_by_tag_name('body'))
-
- The tricky thing here is that there's really no such thing as a "page load,"
- especially in modern Web apps that generate HTML dynamically after the
- server generates the initial document. So, simply checking for the presence
- of ``<body>`` in the response might not necessarily be appropriate for all
- use cases. Please refer to the `Selenium FAQ`_ and
- `Selenium documentation`_ for more information.
-
- .. _Selenium FAQ: http://code.google.com/p/selenium/wiki/FrequentlyAskedQuestions#Q:_WebDriver_fails_to_find_elements_/_Does_not_block_on_page_loa
- .. _Selenium documentation: http://seleniumhq.org/docs/04_webdriver_advanced.html#explicit-waits
-
-Test cases features
--------------------
-
-Default test client
-~~~~~~~~~~~~~~~~~~~
-
-.. attribute:: SimpleTestCase.client
-
-Every test case in a ``django.test.*TestCase`` instance has access to an
-instance of a Django test client. This client can be accessed as
-``self.client``. This client is recreated for each test, so you don't have to
-worry about state (such as cookies) carrying over from one test to another.
-
-This means, instead of instantiating a ``Client`` in each test::
-
- import unittest
- from django.test import Client
-
- class SimpleTest(unittest.TestCase):
- def test_details(self):
- client = Client()
- response = client.get('/customer/details/')
- self.assertEqual(response.status_code, 200)
-
- def test_index(self):
- client = Client()
- response = client.get('/customer/index/')
- self.assertEqual(response.status_code, 200)
-
-...you can just refer to ``self.client``, like so::
-
- from django.test import TestCase
-
- class SimpleTest(TestCase):
- def test_details(self):
- response = self.client.get('/customer/details/')
- self.assertEqual(response.status_code, 200)
-
- def test_index(self):
- response = self.client.get('/customer/index/')
- self.assertEqual(response.status_code, 200)
-
-Customizing the test client
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. attribute:: SimpleTestCase.client_class
-
-If you want to use a different ``Client`` class (for example, a subclass
-with customized behavior), use the :attr:`~SimpleTestCase.client_class` class
-attribute::
-
- from django.test import TestCase, Client
-
- class MyTestClient(Client):
- # Specialized methods for your environment...
-
- class MyTest(TestCase):
- client_class = MyTestClient
-
- def test_my_stuff(self):
- # Here self.client is an instance of MyTestClient...
- call_some_test_code()
-
-.. _topics-testing-fixtures:
-
-Fixture loading
-~~~~~~~~~~~~~~~
-
-.. attribute:: TransactionTestCase.fixtures
-
-A test case for a database-backed Web site isn't much use if there isn't any
-data in the database. To make it easy to put test data into the database,
-Django's custom ``TransactionTestCase`` class provides a way of loading
-**fixtures**.
-
-A fixture is a collection of data that Django knows how to import into a
-database. For example, if your site has user accounts, you might set up a
-fixture of fake user accounts in order to populate your database during tests.
-
-The most straightforward way of creating a fixture is to use the
-:djadmin:`manage.py dumpdata <dumpdata>` command. This assumes you
-already have some data in your database. See the :djadmin:`dumpdata
-documentation<dumpdata>` for more details.
-
-.. note::
-
- If you've ever run :djadmin:`manage.py migrate<migrate>`, you've
- already used a fixture without even knowing it! When you call
- :djadmin:`migrate` in the database for the first time, Django
- installs a fixture called ``initial_data``. This gives you a way
- of populating a new database with any initial data, such as a
- default set of categories.
-
- Fixtures with other names can always be installed manually using
- the :djadmin:`manage.py loaddata<loaddata>` command.
-
-.. admonition:: Initial SQL data and testing
-
- Django provides a second way to insert initial data into models --
- the :ref:`custom SQL hook <initial-sql>`. However, this technique
- *cannot* be used to provide initial data for testing purposes.
- Django's test framework flushes the contents of the test database
- after each test; as a result, any data added using the custom SQL
- hook will be lost.
-
-Once you've created a fixture and placed it in a ``fixtures`` directory in one
-of your :setting:`INSTALLED_APPS`, you can use it in your unit tests by
-specifying a ``fixtures`` class attribute on your :class:`django.test.TestCase`
-subclass::
-
- from django.test import TestCase
- from myapp.models import Animal
-
- class AnimalTestCase(TestCase):
- fixtures = ['mammals.json', 'birds']
-
- def setUp(self):
- # Test definitions as before.
- call_setup_methods()
-
- def testFluffyAnimals(self):
- # A test that uses the fixtures.
- call_some_test_code()
-
-Here's specifically what will happen:
-
-* At the start of each test case, before ``setUp()`` is run, Django will
- flush the database, returning the database to the state it was in
- directly after :djadmin:`migrate` was called.
-
-* Then, all the named fixtures are installed. In this example, Django will
- install any JSON fixture named ``mammals``, followed by any fixture named
- ``birds``. See the :djadmin:`loaddata` documentation for more
- details on defining and installing fixtures.
-
-This flush/load procedure is repeated for each test in the test case, so you
-can be certain that the outcome of a test will not be affected by another test,
-or by the order of test execution.
-
-By default, fixtures are only loaded into the ``default`` database. If you are
-using multiple databases and set :attr:`multi_db=True
-<TransactionTestCase.multi_db>`, fixtures will be loaded into all databases.
-
-URLconf configuration
-~~~~~~~~~~~~~~~~~~~~~
-
-.. attribute:: SimpleTestCase.urls
-
-If your application provides views, you may want to include tests that use the
-test client to exercise those views. However, an end user is free to deploy the
-views in your application at any URL of their choosing. This means that your
-tests can't rely upon the fact that your views will be available at a
-particular URL.
-
-In order to provide a reliable URL space for your test,
-``django.test.*TestCase`` classes provide the ability to customize the URLconf
-configuration for the duration of the execution of a test suite. If your
-``*TestCase`` instance defines an ``urls`` attribute, the ``*TestCase`` will use
-the value of that attribute as the :setting:`ROOT_URLCONF` for the duration
-of that test.
-
-For example::
-
- from django.test import TestCase
-
- class TestMyViews(TestCase):
- urls = 'myapp.test_urls'
-
- def testIndexPageView(self):
- # Here you'd test your view using ``Client``.
- call_some_test_code()
-
-This test case will use the contents of ``myapp.test_urls`` as the
-URLconf for the duration of the test case.
-
-.. _emptying-test-outbox:
-
-Multi-database support
-~~~~~~~~~~~~~~~~~~~~~~
-
-.. attribute:: TransactionTestCase.multi_db
-
-Django sets up a test database corresponding to every database that is
-defined in the :setting:`DATABASES` definition in your settings
-file. However, a big part of the time taken to run a Django TestCase
-is consumed by the call to ``flush`` that ensures that you have a
-clean database at the start of each test run. If you have multiple
-databases, multiple flushes are required (one for each database),
-which can be a time consuming activity -- especially if your tests
-don't need to test multi-database activity.
-
-As an optimization, Django only flushes the ``default`` database at
-the start of each test run. If your setup contains multiple databases,
-and you have a test that requires every database to be clean, you can
-use the ``multi_db`` attribute on the test suite to request a full
-flush.
-
-For example::
-
- class TestMyViews(TestCase):
- multi_db = True
-
- def testIndexPageView(self):
- call_some_test_code()
-
-This test case will flush *all* the test databases before running
-``testIndexPageView``.
-
-The ``multi_db`` flag also affects into which databases the
-attr:`TransactionTestCase.fixtures` are loaded. By default (when
-``multi_db=False``), fixtures are only loaded into the ``default`` database.
-If ``multi_db=True``, fixtures are loaded into all databases.
-
-.. _overriding-settings:
-
-Overriding settings
-~~~~~~~~~~~~~~~~~~~
-
-.. method:: SimpleTestCase.settings
-
-For testing purposes it's often useful to change a setting temporarily and
-revert to the original value after running the testing code. For this use case
-Django provides a standard Python context manager (see :pep:`343`) called
-:meth:`~django.test.SimpleTestCase.settings`, which can be used like this::
-
- from django.test import TestCase
-
- class LoginTestCase(TestCase):
-
- def test_login(self):
-
- # First check for the default behavior
- response = self.client.get('/sekrit/')
- self.assertRedirects(response, '/accounts/login/?next=/sekrit/')
-
- # Then override the LOGIN_URL setting
- with self.settings(LOGIN_URL='/other/login/'):
- response = self.client.get('/sekrit/')
- self.assertRedirects(response, '/other/login/?next=/sekrit/')
-
-This example will override the :setting:`LOGIN_URL` setting for the code
-in the ``with`` block and reset its value to the previous state afterwards.
-
-.. method:: SimpleTestCase.modify_settings
-
-.. versionadded:: 1.7
-
-It can prove unwieldy to redefine settings that contain a list of values. In
-practice, adding or removing values is often sufficient. The
-:meth:`~django.test.SimpleTestCase.modify_settings` context manager makes it
-easy::
-
- from django.test import TestCase
-
- class MiddlewareTestCase(TestCase):
-
- def test_cache_middleware(self):
- with self.modify_settings(MIDDLEWARE_CLASSES={
- 'append': 'django.middleware.cache.FetchFromCacheMiddleware',
- 'prepend': 'django.middleware.cache.UpdateCacheMiddleware',
- 'remove': [
- 'django.contrib.sessions.middleware.SessionMiddleware',
- 'django.contrib.auth.middleware.AuthenticationMiddleware',
- 'django.contrib.messages.middleware.MessageMiddleware',
- ],
- }):
- response = self.client.get('/')
- # ...
-
-For each action, you can supply either a list of values or a string. When the
-value already exists in the list, ``append`` and ``prepend`` have no effect;
-neither does ``remove`` when the value doesn't exist.
-
-.. function:: override_settings
-
-In case you want to override a setting for a test method, Django provides the
-:func:`~django.test.override_settings` decorator (see :pep:`318`). It's used
-like this::
-
- from django.test import TestCase, override_settings
-
- class LoginTestCase(TestCase):
-
- @override_settings(LOGIN_URL='/other/login/')
- def test_login(self):
- response = self.client.get('/sekrit/')
- self.assertRedirects(response, '/other/login/?next=/sekrit/')
-
-The decorator can also be applied to :class:`~django.test.TestCase` classes::
-
- from django.test import TestCase, override_settings
-
- @override_settings(LOGIN_URL='/other/login/')
- class LoginTestCase(TestCase):
-
- def test_login(self):
- response = self.client.get('/sekrit/')
- self.assertRedirects(response, '/other/login/?next=/sekrit/')
-
-.. versionchanged:: 1.7
-
- Previously, ``override_settings`` was imported from ``django.test.utils``.
-
-.. function:: modify_settings
-
-.. versionadded:: 1.7
-
-Likewise, Django provides the :func:`~django.test.modify_settings`
-decorator::
-
- from django.test import TestCase, modify_settings
-
- class MiddlewareTestCase(TestCase):
-
- @modify_settings(MIDDLEWARE_CLASSES={
- 'append': 'django.middleware.cache.FetchFromCacheMiddleware',
- 'prepend': 'django.middleware.cache.UpdateCacheMiddleware',
- })
- def test_cache_middleware(self):
- response = self.client.get('/')
- # ...
-
-The decorator can also be applied to test case classes::
-
- from django.test import TestCase, modify_settings
-
- @modify_settings(MIDDLEWARE_CLASSES={
- 'append': 'django.middleware.cache.FetchFromCacheMiddleware',
- 'prepend': 'django.middleware.cache.UpdateCacheMiddleware',
- })
- class MiddlewareTestCase(TestCase):
-
- def test_cache_middleware(self):
- response = self.client.get('/')
- # ...
-
-.. note::
-
- When given a class, these decorators modify the class directly and return
- it; they don't create and return a modified copy of it. So if you try to
- tweak the above examples to assign the return value to a different name
- than ``LoginTestCase`` or ``MiddlewareTestCase``, you may be surprised to
- find that the original test case classes are still equally affected by the
- decorator. For a given class, :func:`~django.test.modify_settings` is
- always applied after :func:`~django.test.override_settings`.
-
-.. warning::
-
- The settings file contains some settings that are only consulted during
- initialization of Django internals. If you change them with
- ``override_settings``, the setting is changed if you access it via the
- ``django.conf.settings`` module, however, Django's internals access it
- differently. Effectively, using :func:`~django.test.override_settings` or
- :func:`~django.test.modify_settings` with these settings is probably not
- going to do what you expect it to do.
-
- We do not recommend altering the :setting:`DATABASES` setting. Altering
- the :setting:`CACHES` setting is possible, but a bit tricky if you are
- using internals that make using of caching, like
- :mod:`django.contrib.sessions`. For example, you will have to reinitialize
- the session backend in a test that uses cached sessions and overrides
- :setting:`CACHES`.
-
-You can also simulate the absence of a setting by deleting it after settings
-have been overridden, like this::
-
- @override_settings()
- def test_something(self):
- del settings.LOGIN_URL
- ...
-
-When overriding settings, make sure to handle the cases in which your app's
-code uses a cache or similar feature that retains state even if the setting is
-changed. Django provides the :data:`django.test.signals.setting_changed`
-signal that lets you register callbacks to clean up and otherwise reset state
-when settings are changed.
-
-Django itself uses this signal to reset various data:
-
-================================ ========================
-Overridden settings Data reset
-================================ ========================
-USE_TZ, TIME_ZONE Databases timezone
-TEMPLATE_CONTEXT_PROCESSORS Context processors cache
-TEMPLATE_LOADERS Template loaders cache
-SERIALIZATION_MODULES Serializers cache
-LOCALE_PATHS, LANGUAGE_CODE Default translation and loaded translations
-MEDIA_ROOT, DEFAULT_FILE_STORAGE Default file storage
-================================ ========================
-
-Emptying the test outbox
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-If you use any of Django's custom ``TestCase`` classes, the test runner will
-clear the contents of the test email outbox at the start of each test case.
-
-For more detail on email services during tests, see `Email services`_ below.
-
-.. _assertions:
-
-Assertions
-~~~~~~~~~~
-
-As Python's normal :class:`unittest.TestCase` class implements assertion methods
-such as :meth:`~unittest.TestCase.assertTrue` and
-:meth:`~unittest.TestCase.assertEqual`, Django's custom :class:`TestCase` class
-provides a number of custom assertion methods that are useful for testing Web
-applications:
-
-The failure messages given by most of these assertion methods can be customized
-with the ``msg_prefix`` argument. This string will be prefixed to any failure
-message generated by the assertion. This allows you to provide additional
-details that may help you to identify the location and cause of an failure in
-your test suite.
-
-.. method:: SimpleTestCase.assertRaisesMessage(expected_exception, expected_message, callable_obj=None, *args, **kwargs)
-
- Asserts that execution of callable ``callable_obj`` raised the
- ``expected_exception`` exception and that such exception has an
- ``expected_message`` representation. Any other outcome is reported as a
- failure. Similar to unittest's :meth:`~unittest.TestCase.assertRaisesRegexp`
- with the difference that ``expected_message`` isn't a regular expression.
-
-.. method:: SimpleTestCase.assertFieldOutput(self, fieldclass, valid, invalid, field_args=None, field_kwargs=None, empty_value=u'')
-
- Asserts that a form field behaves correctly with various inputs.
-
- :param fieldclass: the class of the field to be tested.
- :param valid: a dictionary mapping valid inputs to their expected cleaned
- values.
- :param invalid: a dictionary mapping invalid inputs to one or more raised
- error messages.
- :param field_args: the args passed to instantiate the field.
- :param field_kwargs: the kwargs passed to instantiate the field.
- :param empty_value: the expected clean output for inputs in ``empty_values``.
-
- For example, the following code tests that an ``EmailField`` accepts
- "a@a.com" as a valid email address, but rejects "aaa" with a reasonable
- error message::
-
- self.assertFieldOutput(EmailField, {'a@a.com': 'a@a.com'}, {'aaa': [u'Enter a valid email address.']})
-
-.. method:: SimpleTestCase.assertFormError(response, form, field, errors, msg_prefix='')
-
- Asserts that a field on a form raises the provided list of errors when
- rendered on the form.
-
- ``form`` is the name the ``Form`` instance was given in the template
- context.
-
- ``field`` is the name of the field on the form to check. If ``field``
- has a value of ``None``, non-field errors (errors you can access via
- ``form.non_field_errors()``) will be checked.
-
- ``errors`` is an error string, or a list of error strings, that are
- expected as a result of form validation.
-
-.. method:: SimpleTestCase.assertFormsetError(response, formset, form_index, field, errors, msg_prefix='')
-
- .. versionadded:: 1.6
-
- Asserts that the ``formset`` raises the provided list of errors when
- rendered.
-
- ``formset`` is the name the ``Formset`` instance was given in the template
- context.
-
- ``form_index`` is the number of the form within the ``Formset``. If
- ``form_index`` has a value of ``None``, non-form errors (errors you can
- access via ``formset.non_form_errors()``) will be checked.
-
- ``field`` is the name of the field on the form to check. If ``field``
- has a value of ``None``, non-field errors (errors you can access via
- ``form.non_field_errors()``) will be checked.
-
- ``errors`` is an error string, or a list of error strings, that are
- expected as a result of form validation.
-
-.. method:: SimpleTestCase.assertContains(response, text, count=None, status_code=200, msg_prefix='', html=False)
-
- Asserts that a ``Response`` instance produced the given ``status_code`` and
- that ``text`` appears in the content of the response. If ``count`` is
- provided, ``text`` must occur exactly ``count`` times in the response.
-
- Set ``html`` to ``True`` to handle ``text`` as HTML. The comparison with
- the response content will be based on HTML semantics instead of
- character-by-character equality. Whitespace is ignored in most cases,
- attribute ordering is not significant. See
- :meth:`~SimpleTestCase.assertHTMLEqual` for more details.
-
-.. method:: SimpleTestCase.assertNotContains(response, text, status_code=200, msg_prefix='', html=False)
-
- Asserts that a ``Response`` instance produced the given ``status_code`` and
- that ``text`` does not appears in the content of the response.
-
- Set ``html`` to ``True`` to handle ``text`` as HTML. The comparison with
- the response content will be based on HTML semantics instead of
- character-by-character equality. Whitespace is ignored in most cases,
- attribute ordering is not significant. See
- :meth:`~SimpleTestCase.assertHTMLEqual` for more details.
-
-.. method:: SimpleTestCase.assertTemplateUsed(response, template_name, msg_prefix='')
-
- Asserts that the template with the given name was used in rendering the
- response.
-
- The name is a string such as ``'admin/index.html'``.
-
- You can use this as a context manager, like this::
-
- with self.assertTemplateUsed('index.html'):
- render_to_string('index.html')
- with self.assertTemplateUsed(template_name='index.html'):
- render_to_string('index.html')
-
-.. method:: SimpleTestCase.assertTemplateNotUsed(response, template_name, msg_prefix='')
-
- Asserts that the template with the given name was *not* used in rendering
- the response.
-
- You can use this as a context manager in the same way as
- :meth:`~SimpleTestCase.assertTemplateUsed`.
-
-.. method:: SimpleTestCase.assertRedirects(response, expected_url, status_code=302, target_status_code=200, msg_prefix='', fetch_redirect_response=True)
-
- Asserts that the response return a ``status_code`` redirect status, it
- redirected to ``expected_url`` (including any GET data), and the final
- page was received with ``target_status_code``.
-
- If your request used the ``follow`` argument, the ``expected_url`` and
- ``target_status_code`` will be the url and status code for the final
- point of the redirect chain.
-
- .. versionadded:: 1.7
-
- If ``fetch_redirect_response`` is ``False``, the final page won't be
- loaded. Since the test client can't fetch externals URLs, this is
- particularly useful if ``expected_url`` isn't part of your Django app.
-
- .. versionadded:: 1.7
-
- Scheme is handled correctly when making comparisons between two URLs. If
- there isn't any scheme specified in the location where we are redirected to,
- the original request's scheme is used. If present, the scheme in
- ``expected_url`` is the one used to make the comparisons to.
-
-.. method:: SimpleTestCase.assertHTMLEqual(html1, html2, msg=None)
-
- Asserts that the strings ``html1`` and ``html2`` are equal. The comparison
- is based on HTML semantics. The comparison takes following things into
- account:
-
- * Whitespace before and after HTML tags is ignored.
- * All types of whitespace are considered equivalent.
- * All open tags are closed implicitly, e.g. when a surrounding tag is
- closed or the HTML document ends.
- * Empty tags are equivalent to their self-closing version.
- * The ordering of attributes of an HTML element is not significant.
- * Attributes without an argument are equal to attributes that equal in
- name and value (see the examples).
-
- The following examples are valid tests and don't raise any
- ``AssertionError``::
-
- self.assertHTMLEqual('<p>Hello <b>world!</p>',
- '''<p>
- Hello <b>world! <b/>
- </p>''')
- self.assertHTMLEqual(
- '<input type="checkbox" checked="checked" id="id_accept_terms" />',
- '<input id="id_accept_terms" type='checkbox' checked>')
-
- ``html1`` and ``html2`` must be valid HTML. An ``AssertionError`` will be
- raised if one of them cannot be parsed.
-
- Output in case of error can be customized with the ``msg`` argument.
-
-.. method:: SimpleTestCase.assertHTMLNotEqual(html1, html2, msg=None)
-
- Asserts that the strings ``html1`` and ``html2`` are *not* equal. The
- comparison is based on HTML semantics. See
- :meth:`~SimpleTestCase.assertHTMLEqual` for details.
-
- ``html1`` and ``html2`` must be valid HTML. An ``AssertionError`` will be
- raised if one of them cannot be parsed.
-
- Output in case of error can be customized with the ``msg`` argument.
-
-.. method:: SimpleTestCase.assertXMLEqual(xml1, xml2, msg=None)
-
- Asserts that the strings ``xml1`` and ``xml2`` are equal. The
- comparison is based on XML semantics. Similarly to
- :meth:`~SimpleTestCase.assertHTMLEqual`, the comparison is
- made on parsed content, hence only semantic differences are considered, not
- syntax differences. When unvalid XML is passed in any parameter, an
- ``AssertionError`` is always raised, even if both string are identical.
-
- Output in case of error can be customized with the ``msg`` argument.
-
-.. method:: SimpleTestCase.assertXMLNotEqual(xml1, xml2, msg=None)
-
- Asserts that the strings ``xml1`` and ``xml2`` are *not* equal. The
- comparison is based on XML semantics. See
- :meth:`~SimpleTestCase.assertXMLEqual` for details.
-
- Output in case of error can be customized with the ``msg`` argument.
-
-.. method:: SimpleTestCase.assertInHTML(needle, haystack, count=None, msg_prefix='')
-
- Asserts that the HTML fragment ``needle`` is contained in the ``haystack`` one.
-
- If the ``count`` integer argument is specified, then additionally the number
- of ``needle`` occurrences will be strictly verified.
-
- Whitespace in most cases is ignored, and attribute ordering is not
- significant. The passed-in arguments must be valid HTML.
-
-.. method:: SimpleTestCase.assertJSONEqual(raw, expected_data, msg=None)
-
- Asserts that the JSON fragments ``raw`` and ``expected_data`` are equal.
- Usual JSON non-significant whitespace rules apply as the heavyweight is
- delegated to the :mod:`json` library.
-
- Output in case of error can be customized with the ``msg`` argument.
-
-.. method:: TransactionTestCase.assertQuerysetEqual(qs, values, transform=repr, ordered=True)
-
- Asserts that a queryset ``qs`` returns a particular list of values ``values``.
-
- The comparison of the contents of ``qs`` and ``values`` is performed using
- the function ``transform``; by default, this means that the ``repr()`` of
- each value is compared. Any other callable can be used if ``repr()`` doesn't
- provide a unique or helpful comparison.
-
- By default, the comparison is also ordering dependent. If ``qs`` doesn't
- provide an implicit ordering, you can set the ``ordered`` parameter to
- ``False``, which turns the comparison into a Python set comparison.
-
- .. versionchanged:: 1.6
-
- The method now checks for undefined order and raises ``ValueError``
- if undefined order is spotted. The ordering is seen as undefined if
- the given ``qs`` isn't ordered and the comparison is against more
- than one ordered values.
-
-.. method:: TransactionTestCase.assertNumQueries(num, func, *args, **kwargs)
-
- Asserts that when ``func`` is called with ``*args`` and ``**kwargs`` that
- ``num`` database queries are executed.
-
- If a ``"using"`` key is present in ``kwargs`` it is used as the database
- alias for which to check the number of queries. If you wish to call a
- function with a ``using`` parameter you can do it by wrapping the call with
- a ``lambda`` to add an extra parameter::
-
- self.assertNumQueries(7, lambda: my_function(using=7))
-
- You can also use this as a context manager::
-
- with self.assertNumQueries(2):
- Person.objects.create(name="Aaron")
- Person.objects.create(name="Daniel")
-
-.. _topics-testing-email:
-
-Email services
---------------
-
-If any of your Django views send email using :doc:`Django's email
-functionality </topics/email>`, you probably don't want to send email each time
-you run a test using that view. For this reason, Django's test runner
-automatically redirects all Django-sent email to a dummy outbox. This lets you
-test every aspect of sending email -- from the number of messages sent to the
-contents of each message -- without actually sending the messages.
-
-The test runner accomplishes this by transparently replacing the normal
-email backend with a testing backend.
-(Don't worry -- this has no effect on any other email senders outside of
-Django, such as your machine's mail server, if you're running one.)
-
-.. currentmodule:: django.core.mail
-
-.. data:: django.core.mail.outbox
-
-During test running, each outgoing email is saved in
-``django.core.mail.outbox``. This is a simple list of all
-:class:`~django.core.mail.EmailMessage` instances that have been sent.
-The ``outbox`` attribute is a special attribute that is created *only* when
-the ``locmem`` email backend is used. It doesn't normally exist as part of the
-:mod:`django.core.mail` module and you can't import it directly. The code
-below shows how to access this attribute correctly.
-
-Here's an example test that examines ``django.core.mail.outbox`` for length
-and contents::
-
- from django.core import mail
- from django.test import TestCase
-
- class EmailTest(TestCase):
- def test_send_email(self):
- # Send message.
- mail.send_mail('Subject here', 'Here is the message.',
- 'from@example.com', ['to@example.com'],
- fail_silently=False)
-
- # Test that one message has been sent.
- self.assertEqual(len(mail.outbox), 1)
-
- # Verify that the subject of the first message is correct.
- self.assertEqual(mail.outbox[0].subject, 'Subject here')
-
-As noted :ref:`previously <emptying-test-outbox>`, the test outbox is emptied
-at the start of every test in a Django ``*TestCase``. To empty the outbox
-manually, assign the empty list to ``mail.outbox``::
-
- from django.core import mail
-
- # Empty the test outbox
- mail.outbox = []
-
-.. _skipping-tests:
-
-Skipping tests
---------------
-
-.. currentmodule:: django.test
-
-The unittest library provides the :func:`@skipIf <unittest.skipIf>` and
-:func:`@skipUnless <unittest.skipUnless>` decorators to allow you to skip tests
-if you know ahead of time that those tests are going to fail under certain
-conditions.
-
-For example, if your test requires a particular optional library in order to
-succeed, you could decorate the test case with :func:`@skipIf
-<unittest.skipIf>`. Then, the test runner will report that the test wasn't
-executed and why, instead of failing the test or omitting the test altogether.
-
-To supplement these test skipping behaviors, Django provides two
-additional skip decorators. Instead of testing a generic boolean,
-these decorators check the capabilities of the database, and skip the
-test if the database doesn't support a specific named feature.
-
-The decorators use a string identifier to describe database features.
-This string corresponds to attributes of the database connection
-features class. See ``django.db.backends.BaseDatabaseFeatures``
-class for a full list of database features that can be used as a basis
-for skipping tests.
-
-.. function:: skipIfDBFeature(feature_name_string)
-
-Skip the decorated test or ``TestCase`` if the named database feature is
-supported.
-
-For example, the following test will not be executed if the database
-supports transactions (e.g., it would *not* run under PostgreSQL, but
-it would under MySQL with MyISAM tables)::
-
- class MyTests(TestCase):
- @skipIfDBFeature('supports_transactions')
- def test_transaction_behavior(self):
- # ... conditional test code
-
-.. versionchanged:: 1.7
-
- ``skipIfDBFeature`` can now be used to decorate a ``TestCase`` class.
-
-.. function:: skipUnlessDBFeature(feature_name_string)
-
-Skip the decorated test or ``TestCase`` if the named database feature is *not*
-supported.
-
-For example, the following test will only be executed if the database
-supports transactions (e.g., it would run under PostgreSQL, but *not*
-under MySQL with MyISAM tables)::
-
- class MyTests(TestCase):
- @skipUnlessDBFeature('supports_transactions')
- def test_transaction_behavior(self):
- # ... conditional test code
-
-.. versionchanged:: 1.7
-
- ``skipUnlessDBFeature`` can now be used to decorate a ``TestCase`` class.
diff --git a/docs/topics/testing/tools.txt b/docs/topics/testing/tools.txt
new file mode 100644
index 0000000000..d97644fb72
--- /dev/null
+++ b/docs/topics/testing/tools.txt
@@ -0,0 +1,1596 @@
+=============
+Testing tools
+=============
+
+.. currentmodule:: django.test
+
+Django provides a small set of tools that come in handy when writing tests.
+
+.. _test-client:
+
+The test client
+---------------
+
+The test client is a Python class that acts as a dummy Web browser, allowing
+you to test your views and interact with your Django-powered application
+programmatically.
+
+Some of the things you can do with the test client are:
+
+* Simulate GET and POST requests on a URL and observe the response --
+ everything from low-level HTTP (result headers and status codes) to
+ page content.
+
+* See the chain of redirects (if any) and check the URL and status code at
+ each step.
+
+* Test that a given request is rendered by a given Django template, with
+ a template context that contains certain values.
+
+Note that the test client is not intended to be a replacement for Selenium_ or
+other "in-browser" frameworks. Django's test client has a different focus. In
+short:
+
+* Use Django's test client to establish that the correct template is being
+ rendered and that the template is passed the correct context data.
+
+* Use in-browser frameworks like Selenium_ to test *rendered* HTML and the
+ *behavior* of Web pages, namely JavaScript functionality. Django also
+ provides special support for those frameworks; see the section on
+ :class:`~django.test.LiveServerTestCase` for more details.
+
+A comprehensive test suite should use a combination of both test types.
+
+Overview and a quick example
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To use the test client, instantiate ``django.test.Client`` and retrieve
+Web pages::
+
+ >>> from django.test import Client
+ >>> c = Client()
+ >>> response = c.post('/login/', {'username': 'john', 'password': 'smith'})
+ >>> response.status_code
+ 200
+ >>> response = c.get('/customer/details/')
+ >>> response.content
+ '<!DOCTYPE html...'
+
+As this example suggests, you can instantiate ``Client`` from within a session
+of the Python interactive interpreter.
+
+Note a few important things about how the test client works:
+
+* The test client does *not* require the Web server to be running. In fact,
+ it will run just fine with no Web server running at all! That's because
+ it avoids the overhead of HTTP and deals directly with the Django
+ framework. This helps make the unit tests run quickly.
+
+* When retrieving pages, remember to specify the *path* of the URL, not the
+ whole domain. For example, this is correct::
+
+ >>> c.get('/login/')
+
+ This is incorrect::
+
+ >>> c.get('http://www.example.com/login/')
+
+ The test client is not capable of retrieving Web pages that are not
+ powered by your Django project. If you need to retrieve other Web pages,
+ use a Python standard library module such as :mod:`urllib` or
+ :mod:`urllib2`.
+
+* To resolve URLs, the test client uses whatever URLconf is pointed-to by
+ your :setting:`ROOT_URLCONF` setting.
+
+* Although the above example would work in the Python interactive
+ interpreter, some of the test client's functionality, notably the
+ template-related functionality, is only available *while tests are
+ running*.
+
+ The reason for this is that Django's test runner performs a bit of black
+ magic in order to determine which template was loaded by a given view.
+ This black magic (essentially a patching of Django's template system in
+ memory) only happens during test running.
+
+* By default, the test client will disable any CSRF checks
+ performed by your site.
+
+ If, for some reason, you *want* the test client to perform CSRF
+ checks, you can create an instance of the test client that
+ enforces CSRF checks. To do this, pass in the
+ ``enforce_csrf_checks`` argument when you construct your
+ client::
+
+ >>> from django.test import Client
+ >>> csrf_client = Client(enforce_csrf_checks=True)
+
+Making requests
+~~~~~~~~~~~~~~~
+
+Use the ``django.test.Client`` class to make requests.
+
+.. class:: Client(enforce_csrf_checks=False, **defaults)
+
+ It requires no arguments at time of construction. However, you can use
+ keywords arguments to specify some default headers. For example, this will
+ send a ``User-Agent`` HTTP header in each request::
+
+ >>> c = Client(HTTP_USER_AGENT='Mozilla/5.0')
+
+ The values from the ``extra`` keywords arguments passed to
+ :meth:`~django.test.Client.get()`,
+ :meth:`~django.test.Client.post()`, etc. have precedence over
+ the defaults passed to the class constructor.
+
+ The ``enforce_csrf_checks`` argument can be used to test CSRF
+ protection (see above).
+
+ Once you have a ``Client`` instance, you can call any of the following
+ methods:
+
+ .. method:: Client.get(path, data={}, follow=False, secure=False, **extra)
+
+ .. versionadded:: 1.7
+
+ The ``secure`` argument was added.
+
+ Makes a GET request on the provided ``path`` and returns a ``Response``
+ object, which is documented below.
+
+ The key-value pairs in the ``data`` dictionary are used to create a GET
+ data payload. For example::
+
+ >>> c = Client()
+ >>> c.get('/customers/details/', {'name': 'fred', 'age': 7})
+
+ ...will result in the evaluation of a GET request equivalent to::
+
+ /customers/details/?name=fred&age=7
+
+ The ``extra`` keyword arguments parameter can be used to specify
+ headers to be sent in the request. For example::
+
+ >>> c = Client()
+ >>> c.get('/customers/details/', {'name': 'fred', 'age': 7},
+ ... HTTP_X_REQUESTED_WITH='XMLHttpRequest')
+
+ ...will send the HTTP header ``HTTP_X_REQUESTED_WITH`` to the
+ details view, which is a good way to test code paths that use the
+ :meth:`django.http.HttpRequest.is_ajax()` method.
+
+ .. admonition:: CGI specification
+
+ The headers sent via ``**extra`` should follow CGI_ specification.
+ For example, emulating a different "Host" header as sent in the
+ HTTP request from the browser to the server should be passed
+ as ``HTTP_HOST``.
+
+ .. _CGI: http://www.w3.org/CGI/
+
+ If you already have the GET arguments in URL-encoded form, you can
+ use that encoding instead of using the data argument. For example,
+ the previous GET request could also be posed as::
+
+ >>> c = Client()
+ >>> c.get('/customers/details/?name=fred&age=7')
+
+ If you provide a URL with both an encoded GET data and a data argument,
+ the data argument will take precedence.
+
+ If you set ``follow`` to ``True`` the client will follow any redirects
+ and a ``redirect_chain`` attribute will be set in the response object
+ containing tuples of the intermediate urls and status codes.
+
+ If you had a URL ``/redirect_me/`` that redirected to ``/next/``, that
+ redirected to ``/final/``, this is what you'd see::
+
+ >>> response = c.get('/redirect_me/', follow=True)
+ >>> response.redirect_chain
+ [(u'http://testserver/next/', 302), (u'http://testserver/final/', 302)]
+
+ If you set ``secure`` to ``True`` the client will emulate an HTTPS
+ request.
+
+ .. method:: Client.post(path, data={}, content_type=MULTIPART_CONTENT, follow=False, secure=False, **extra)
+
+ Makes a POST request on the provided ``path`` and returns a
+ ``Response`` object, which is documented below.
+
+ The key-value pairs in the ``data`` dictionary are used to submit POST
+ data. For example::
+
+ >>> c = Client()
+ >>> c.post('/login/', {'name': 'fred', 'passwd': 'secret'})
+
+ ...will result in the evaluation of a POST request to this URL::
+
+ /login/
+
+ ...with this POST data::
+
+ name=fred&passwd=secret
+
+ If you provide ``content_type`` (e.g. :mimetype:`text/xml` for an XML
+ payload), the contents of ``data`` will be sent as-is in the POST
+ request, using ``content_type`` in the HTTP ``Content-Type`` header.
+
+ If you don't provide a value for ``content_type``, the values in
+ ``data`` will be transmitted with a content type of
+ :mimetype:`multipart/form-data`. In this case, the key-value pairs in
+ ``data`` will be encoded as a multipart message and used to create the
+ POST data payload.
+
+ To submit multiple values for a given key -- for example, to specify
+ the selections for a ``<select multiple>`` -- provide the values as a
+ list or tuple for the required key. For example, this value of ``data``
+ would submit three selected values for the field named ``choices``::
+
+ {'choices': ('a', 'b', 'd')}
+
+ Submitting files is a special case. To POST a file, you need only
+ provide the file field name as a key, and a file handle to the file you
+ wish to upload as a value. For example::
+
+ >>> c = Client()
+ >>> with open('wishlist.doc') as fp:
+ ... c.post('/customers/wishes/', {'name': 'fred', 'attachment': fp})
+
+ (The name ``attachment`` here is not relevant; use whatever name your
+ file-processing code expects.)
+
+ Note that if you wish to use the same file handle for multiple
+ ``post()`` calls then you will need to manually reset the file
+ pointer between posts. The easiest way to do this is to
+ manually close the file after it has been provided to
+ ``post()``, as demonstrated above.
+
+ You should also ensure that the file is opened in a way that
+ allows the data to be read. If your file contains binary data
+ such as an image, this means you will need to open the file in
+ ``rb`` (read binary) mode.
+
+ The ``extra`` argument acts the same as for :meth:`Client.get`.
+
+ If the URL you request with a POST contains encoded parameters, these
+ parameters will be made available in the request.GET data. For example,
+ if you were to make the request::
+
+ >>> c.post('/login/?visitor=true', {'name': 'fred', 'passwd': 'secret'})
+
+ ... the view handling this request could interrogate request.POST
+ to retrieve the username and password, and could interrogate request.GET
+ to determine if the user was a visitor.
+
+ If you set ``follow`` to ``True`` the client will follow any redirects
+ and a ``redirect_chain`` attribute will be set in the response object
+ containing tuples of the intermediate urls and status codes.
+
+ If you set ``secure`` to ``True`` the client will emulate an HTTPS
+ request.
+
+ .. method:: Client.head(path, data={}, follow=False, secure=False, **extra)
+
+ Makes a HEAD request on the provided ``path`` and returns a
+ ``Response`` object. This method works just like :meth:`Client.get`,
+ including the ``follow``, ``secure`` and ``extra`` arguments, except
+ it does not return a message body.
+
+ .. method:: Client.options(path, data='', content_type='application/octet-stream', follow=False, secure=False, **extra)
+
+ Makes an OPTIONS request on the provided ``path`` and returns a
+ ``Response`` object. Useful for testing RESTful interfaces.
+
+ When ``data`` is provided, it is used as the request body, and
+ a ``Content-Type`` header is set to ``content_type``.
+
+ The ``follow``, ``secure`` and ``extra`` arguments act the same as for
+ :meth:`Client.get`.
+
+ .. method:: Client.put(path, data='', content_type='application/octet-stream', follow=False, secure=False, **extra)
+
+ Makes a PUT request on the provided ``path`` and returns a
+ ``Response`` object. Useful for testing RESTful interfaces.
+
+ When ``data`` is provided, it is used as the request body, and
+ a ``Content-Type`` header is set to ``content_type``.
+
+ The ``follow``, ``secure`` and ``extra`` arguments act the same as for
+ :meth:`Client.get`.
+
+ .. method:: Client.patch(path, data='', content_type='application/octet-stream', follow=False, secure=False, **extra)
+
+ Makes a PATCH request on the provided ``path`` and returns a
+ ``Response`` object. Useful for testing RESTful interfaces.
+
+ The ``follow``, ``secure`` and ``extra`` arguments act the same as for
+ :meth:`Client.get`.
+
+ .. method:: Client.delete(path, data='', content_type='application/octet-stream', follow=False, secure=False, **extra)
+
+ Makes an DELETE request on the provided ``path`` and returns a
+ ``Response`` object. Useful for testing RESTful interfaces.
+
+ When ``data`` is provided, it is used as the request body, and
+ a ``Content-Type`` header is set to ``content_type``.
+
+ The ``follow``, ``secure`` and ``extra`` arguments act the same as for
+ :meth:`Client.get`.
+
+ .. method:: Client.login(**credentials)
+
+ If your site uses Django's :doc:`authentication system</topics/auth/index>`
+ and you deal with logging in users, you can use the test client's
+ ``login()`` method to simulate the effect of a user logging into the
+ site.
+
+ After you call this method, the test client will have all the cookies
+ and session data required to pass any login-based tests that may form
+ part of a view.
+
+ The format of the ``credentials`` argument depends on which
+ :ref:`authentication backend <authentication-backends>` you're using
+ (which is configured by your :setting:`AUTHENTICATION_BACKENDS`
+ setting). If you're using the standard authentication backend provided
+ by Django (``ModelBackend``), ``credentials`` should be the user's
+ username and password, provided as keyword arguments::
+
+ >>> c = Client()
+ >>> c.login(username='fred', password='secret')
+
+ # Now you can access a view that's only available to logged-in users.
+
+ If you're using a different authentication backend, this method may
+ require different credentials. It requires whichever credentials are
+ required by your backend's ``authenticate()`` method.
+
+ ``login()`` returns ``True`` if it the credentials were accepted and
+ login was successful.
+
+ Finally, you'll need to remember to create user accounts before you can
+ use this method. As we explained above, the test runner is executed
+ using a test database, which contains no users by default. As a result,
+ user accounts that are valid on your production site will not work
+ under test conditions. You'll need to create users as part of the test
+ suite -- either manually (using the Django model API) or with a test
+ fixture. Remember that if you want your test user to have a password,
+ you can't set the user's password by setting the password attribute
+ directly -- you must use the
+ :meth:`~django.contrib.auth.models.User.set_password()` function to
+ store a correctly hashed password. Alternatively, you can use the
+ :meth:`~django.contrib.auth.models.UserManager.create_user` helper
+ method to create a new user with a correctly hashed password.
+
+ .. versionadded:: 1.7
+
+ Requests made with :meth:`~django.test.Client.login` go through the
+ request middleware. If you need to control the environment, you can
+ do so at :class:`~django.test.Client` instantiation or with the
+ `Client.defaults` attribute.
+
+ .. method:: Client.logout()
+
+ If your site uses Django's :doc:`authentication system</topics/auth/index>`,
+ the ``logout()`` method can be used to simulate the effect of a user
+ logging out of your site.
+
+ After you call this method, the test client will have all the cookies
+ and session data cleared to defaults. Subsequent requests will appear
+ to come from an :class:`~django.contrib.auth.models.AnonymousUser`.
+
+ .. versionadded:: 1.7
+
+ Requests made with :meth:`~django.test.Client.logout` go through the
+ request middleware. If you need to control the environment, you can
+ do so at :class:`~django.test.Client` instantiation or with the
+ `Client.defaults` attribute.
+
+Testing responses
+~~~~~~~~~~~~~~~~~
+
+The ``get()`` and ``post()`` methods both return a ``Response`` object. This
+``Response`` object is *not* the same as the ``HttpResponse`` object returned
+Django views; the test response object has some additional data useful for
+test code to verify.
+
+Specifically, a ``Response`` object has the following attributes:
+
+.. class:: Response()
+
+ .. attribute:: client
+
+ The test client that was used to make the request that resulted in the
+ response.
+
+ .. attribute:: content
+
+ The body of the response, as a string. This is the final page content as
+ rendered by the view, or any error message.
+
+ .. attribute:: context
+
+ The template ``Context`` instance that was used to render the template that
+ produced the response content.
+
+ If the rendered page used multiple templates, then ``context`` will be a
+ list of ``Context`` objects, in the order in which they were rendered.
+
+ Regardless of the number of templates used during rendering, you can
+ retrieve context values using the ``[]`` operator. For example, the
+ context variable ``name`` could be retrieved using::
+
+ >>> response = client.get('/foo/')
+ >>> response.context['name']
+ 'Arthur'
+
+ .. attribute:: request
+
+ The request data that stimulated the response.
+
+ .. attribute:: status_code
+
+ The HTTP status of the response, as an integer. See
+ :rfc:`2616#section-10` for a full list of HTTP status codes.
+
+ .. attribute:: templates
+
+ A list of ``Template`` instances used to render the final content, in
+ the order they were rendered. For each template in the list, use
+ ``template.name`` to get the template's file name, if the template was
+ loaded from a file. (The name is a string such as
+ ``'admin/index.html'``.)
+
+You can also use dictionary syntax on the response object to query the value
+of any settings in the HTTP headers. For example, you could determine the
+content type of a response using ``response['Content-Type']``.
+
+Exceptions
+~~~~~~~~~~
+
+If you point the test client at a view that raises an exception, that exception
+will be visible in the test case. You can then use a standard ``try ... except``
+block or :meth:`~unittest.TestCase.assertRaises` to test for exceptions.
+
+The only exceptions that are not visible to the test client are ``Http404``,
+``PermissionDenied`` and ``SystemExit``. Django catches these exceptions
+internally and converts them into the appropriate HTTP response codes. In these
+cases, you can check ``response.status_code`` in your test.
+
+Persistent state
+~~~~~~~~~~~~~~~~
+
+The test client is stateful. If a response returns a cookie, then that cookie
+will be stored in the test client and sent with all subsequent ``get()`` and
+``post()`` requests.
+
+Expiration policies for these cookies are not followed. If you want a cookie
+to expire, either delete it manually or create a new ``Client`` instance (which
+will effectively delete all cookies).
+
+A test client has two attributes that store persistent state information. You
+can access these properties as part of a test condition.
+
+.. attribute:: Client.cookies
+
+ A Python :class:`~Cookie.SimpleCookie` object, containing the current values
+ of all the client cookies. See the documentation of the :mod:`Cookie` module
+ for more.
+
+.. attribute:: Client.session
+
+ A dictionary-like object containing session information. See the
+ :doc:`session documentation</topics/http/sessions>` for full details.
+
+ To modify the session and then save it, it must be stored in a variable
+ first (because a new ``SessionStore`` is created every time this property
+ is accessed)::
+
+ def test_something(self):
+ session = self.client.session
+ session['somekey'] = 'test'
+ session.save()
+
+Example
+~~~~~~~
+
+The following is a simple unit test using the test client::
+
+ import unittest
+ from django.test import Client
+
+ class SimpleTest(unittest.TestCase):
+ def setUp(self):
+ # Every test needs a client.
+ self.client = Client()
+
+ def test_details(self):
+ # Issue a GET request.
+ response = self.client.get('/customer/details/')
+
+ # Check that the response is 200 OK.
+ self.assertEqual(response.status_code, 200)
+
+ # Check that the rendered context contains 5 customers.
+ self.assertEqual(len(response.context['customers']), 5)
+
+.. seealso::
+
+ :class:`django.test.RequestFactory`
+
+.. _django-testcase-subclasses:
+
+Provided test case classes
+--------------------------
+
+Normal Python unit test classes extend a base class of
+:class:`unittest.TestCase`. Django provides a few extensions of this base class:
+
+.. _testcase_hierarchy_diagram:
+
+.. figure:: _images/django_unittest_classes_hierarchy.*
+ :alt: Hierarchy of Django unit testing classes (TestCase subclasses)
+ :width: 508
+ :height: 328
+
+ Hierarchy of Django unit testing classes
+
+SimpleTestCase
+~~~~~~~~~~~~~~
+
+.. class:: SimpleTestCase()
+
+A thin subclass of :class:`unittest.TestCase`, it extends it with some basic
+functionality like:
+
+* Saving and restoring the Python warning machinery state.
+* Some useful assertions like:
+
+ * Checking that a callable :meth:`raises a certain exception
+ <SimpleTestCase.assertRaisesMessage>`.
+ * Testing form field :meth:`rendering and error treatment
+ <SimpleTestCase.assertFieldOutput>`.
+ * Testing :meth:`HTML responses for the presence/lack of a given fragment
+ <SimpleTestCase.assertContains>`.
+ * Verifying that a template :meth:`has/hasn't been used to generate a given
+ response content <SimpleTestCase.assertTemplateUsed>`.
+ * Verifying a HTTP :meth:`redirect <SimpleTestCase.assertRedirects>` is
+ performed by the app.
+ * Robustly testing two :meth:`HTML fragments <SimpleTestCase.assertHTMLEqual>`
+ for equality/inequality or :meth:`containment <SimpleTestCase.assertInHTML>`.
+ * Robustly testing two :meth:`XML fragments <SimpleTestCase.assertXMLEqual>`
+ for equality/inequality.
+ * Robustly testing two :meth:`JSON fragments <SimpleTestCase.assertJSONEqual>`
+ for equality.
+
+* The ability to run tests with :ref:`modified settings <overriding-settings>`.
+* Using the :attr:`~SimpleTestCase.client` :class:`~django.test.Client`.
+* Custom test-time :attr:`URL maps <SimpleTestCase.urls>`.
+
+.. versionchanged:: 1.6
+
+ The latter two features were moved from ``TransactionTestCase`` to
+ ``SimpleTestCase`` in Django 1.6.
+
+If you need any of the other more complex and heavyweight Django-specific
+features like:
+
+* Testing or using the ORM.
+* Database :attr:`~TransactionTestCase.fixtures`.
+* Test :ref:`skipping based on database backend features <skipping-tests>`.
+* The remaining specialized :meth:`assert*
+ <TransactionTestCase.assertQuerysetEqual>` methods.
+
+then you should use :class:`~django.test.TransactionTestCase` or
+:class:`~django.test.TestCase` instead.
+
+``SimpleTestCase`` inherits from ``unittest.TestCase``.
+
+TransactionTestCase
+~~~~~~~~~~~~~~~~~~~
+
+.. class:: TransactionTestCase()
+
+Django's ``TestCase`` class (described below) makes use of database transaction
+facilities to speed up the process of resetting the database to a known state
+at the beginning of each test. A consequence of this, however, is that the
+effects of transaction commit and rollback cannot be tested by a Django
+``TestCase`` class. If your test requires testing of such transactional
+behavior, you should use a Django ``TransactionTestCase``.
+
+``TransactionTestCase`` and ``TestCase`` are identical except for the manner
+in which the database is reset to a known state and the ability for test code
+to test the effects of commit and rollback:
+
+* A ``TransactionTestCase`` resets the database after the test runs by
+ truncating all tables. A ``TransactionTestCase`` may call commit and rollback
+ and observe the effects of these calls on the database.
+
+* A ``TestCase``, on the other hand, does not truncate tables after a test.
+ Instead, it encloses the test code in a database transaction that is rolled
+ back at the end of the test. Both explicit commits like
+ ``transaction.commit()`` and implicit ones that may be caused by
+ ``transaction.atomic()`` are replaced with a ``nop`` operation. This
+ guarantees that the rollback at the end of the test restores the database to
+ its initial state.
+
+ When running on a database that does not support rollback (e.g. MySQL with the
+ MyISAM storage engine), ``TestCase`` falls back to initializing the database
+ by truncating tables and reloading initial data.
+
+.. warning::
+
+ While ``commit`` and ``rollback`` operations still *appear* to work when
+ used in ``TestCase``, no actual commit or rollback will be performed by the
+ database. This can cause your tests to pass or fail unexpectedly. Always
+ use ``TransactionTestCase`` when testing transactional behavior.
+
+``TransactionTestCase`` inherits from :class:`~django.test.SimpleTestCase`.
+
+TestCase
+~~~~~~~~
+
+.. class:: TestCase()
+
+This class provides some additional capabilities that can be useful for testing
+Web sites.
+
+Converting a normal :class:`unittest.TestCase` to a Django :class:`TestCase` is
+easy: Just change the base class of your test from ``'unittest.TestCase'`` to
+``'django.test.TestCase'``. All of the standard Python unit test functionality
+will continue to be available, but it will be augmented with some useful
+additions, including:
+
+* Automatic loading of fixtures.
+
+* Wraps each test in a transaction.
+
+* Creates a TestClient instance.
+
+* Django-specific assertions for testing for things like redirection and form
+ errors.
+
+``TestCase`` inherits from :class:`~django.test.TransactionTestCase`.
+
+.. _live-test-server:
+
+LiveServerTestCase
+~~~~~~~~~~~~~~~~~~
+
+.. class:: LiveServerTestCase()
+
+``LiveServerTestCase`` does basically the same as
+:class:`~django.test.TransactionTestCase` with one extra feature: it launches a
+live Django server in the background on setup, and shuts it down on teardown.
+This allows the use of automated test clients other than the
+:ref:`Django dummy client <test-client>` such as, for example, the Selenium_
+client, to execute a series of functional tests inside a browser and simulate a
+real user's actions.
+
+By default the live server's address is ``'localhost:8081'`` and the full URL
+can be accessed during the tests with ``self.live_server_url``. If you'd like
+to change the default address (in the case, for example, where the 8081 port is
+already taken) then you may pass a different one to the :djadmin:`test` command
+via the :djadminopt:`--liveserver` option, for example:
+
+.. code-block:: bash
+
+ ./manage.py test --liveserver=localhost:8082
+
+Another way of changing the default server address is by setting the
+`DJANGO_LIVE_TEST_SERVER_ADDRESS` environment variable somewhere in your
+code (for example, in a :ref:`custom test runner<topics-testing-test_runner>`):
+
+.. code-block:: python
+
+ import os
+ os.environ['DJANGO_LIVE_TEST_SERVER_ADDRESS'] = 'localhost:8082'
+
+In the case where the tests are run by multiple processes in parallel (for
+example, in the context of several simultaneous `continuous integration`_
+builds), the processes will compete for the same address, and therefore your
+tests might randomly fail with an "Address already in use" error. To avoid this
+problem, you can pass a comma-separated list of ports or ranges of ports (at
+least as many as the number of potential parallel processes). For example:
+
+.. code-block:: bash
+
+ ./manage.py test --liveserver=localhost:8082,8090-8100,9000-9200,7041
+
+Then, during test execution, each new live test server will try every specified
+port until it finds one that is free and takes it.
+
+.. _continuous integration: http://en.wikipedia.org/wiki/Continuous_integration
+
+To demonstrate how to use ``LiveServerTestCase``, let's write a simple Selenium
+test. First of all, you need to install the `selenium package`_ into your
+Python path:
+
+.. code-block:: bash
+
+ pip install selenium
+
+Then, add a ``LiveServerTestCase``-based test to your app's tests module
+(for example: ``myapp/tests.py``). The code for this test may look as follows:
+
+.. code-block:: python
+
+ from django.test import LiveServerTestCase
+ from selenium.webdriver.firefox.webdriver import WebDriver
+
+ class MySeleniumTests(LiveServerTestCase):
+ fixtures = ['user-data.json']
+
+ @classmethod
+ def setUpClass(cls):
+ cls.selenium = WebDriver()
+ super(MySeleniumTests, cls).setUpClass()
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.selenium.quit()
+ super(MySeleniumTests, cls).tearDownClass()
+
+ def test_login(self):
+ self.selenium.get('%s%s' % (self.live_server_url, '/login/'))
+ username_input = self.selenium.find_element_by_name("username")
+ username_input.send_keys('myuser')
+ password_input = self.selenium.find_element_by_name("password")
+ password_input.send_keys('secret')
+ self.selenium.find_element_by_xpath('//input[@value="Log in"]').click()
+
+Finally, you may run the test as follows:
+
+.. code-block:: bash
+
+ ./manage.py test myapp.MySeleniumTests.test_login
+
+This example will automatically open Firefox then go to the login page, enter
+the credentials and press the "Log in" button. Selenium offers other drivers in
+case you do not have Firefox installed or wish to use another browser. The
+example above is just a tiny fraction of what the Selenium client can do; check
+out the `full reference`_ for more details.
+
+.. _Selenium: http://seleniumhq.org/
+.. _selenium package: https://pypi.python.org/pypi/selenium
+.. _full reference: http://selenium-python.readthedocs.org/en/latest/api.html
+.. _Firefox: http://www.mozilla.com/firefox/
+
+.. versionchanged:: 1.7
+
+ Before Django 1.7 ``LiveServerTestCase`` used to rely on the
+ :doc:`staticfiles contrib app </howto/static-files/index>` to get the
+ static assets of the application(s) under test transparently served at their
+ expected locations during the execution of these tests.
+
+ In Django 1.7 this dependency of core functionality on a ``contrib``
+ appplication has been removed, because of which ``LiveServerTestCase``
+ ability in this respect has been retrofitted to simply publish the contents
+ of the file system under :setting:`STATIC_ROOT` at the :setting:`STATIC_URL`
+ URL.
+
+ If you use the ``staticfiles`` app in your project and need to perform live
+ testing then you might want to consider using the
+ :class:`~django.contrib.staticfiles.testing.StaticLiveServerCase` subclass
+ shipped with it instead because it's the one that implements the original
+ behavior now. See :ref:`the relevant documentation
+ <staticfiles-testing-support>` for more details.
+
+.. note::
+
+ When using an in-memory SQLite database to run the tests, the same database
+ connection will be shared by two threads in parallel: the thread in which
+ the live server is run and the thread in which the test case is run. It's
+ important to prevent simultaneous database queries via this shared
+ connection by the two threads, as that may sometimes randomly cause the
+ tests to fail. So you need to ensure that the two threads don't access the
+ database at the same time. In particular, this means that in some cases
+ (for example, just after clicking a link or submitting a form), you might
+ need to check that a response is received by Selenium and that the next
+ page is loaded before proceeding with further test execution.
+ Do this, for example, by making Selenium wait until the ``<body>`` HTML tag
+ is found in the response (requires Selenium > 2.13):
+
+ .. code-block:: python
+
+ def test_login(self):
+ from selenium.webdriver.support.wait import WebDriverWait
+ timeout = 2
+ ...
+ self.selenium.find_element_by_xpath('//input[@value="Log in"]').click()
+ # Wait until the response is received
+ WebDriverWait(self.selenium, timeout).until(
+ lambda driver: driver.find_element_by_tag_name('body'))
+
+ The tricky thing here is that there's really no such thing as a "page load,"
+ especially in modern Web apps that generate HTML dynamically after the
+ server generates the initial document. So, simply checking for the presence
+ of ``<body>`` in the response might not necessarily be appropriate for all
+ use cases. Please refer to the `Selenium FAQ`_ and
+ `Selenium documentation`_ for more information.
+
+ .. _Selenium FAQ: http://code.google.com/p/selenium/wiki/FrequentlyAskedQuestions#Q:_WebDriver_fails_to_find_elements_/_Does_not_block_on_page_loa
+ .. _Selenium documentation: http://seleniumhq.org/docs/04_webdriver_advanced.html#explicit-waits
+
+Test cases features
+-------------------
+
+Default test client
+~~~~~~~~~~~~~~~~~~~
+
+.. attribute:: SimpleTestCase.client
+
+Every test case in a ``django.test.*TestCase`` instance has access to an
+instance of a Django test client. This client can be accessed as
+``self.client``. This client is recreated for each test, so you don't have to
+worry about state (such as cookies) carrying over from one test to another.
+
+This means, instead of instantiating a ``Client`` in each test::
+
+ import unittest
+ from django.test import Client
+
+ class SimpleTest(unittest.TestCase):
+ def test_details(self):
+ client = Client()
+ response = client.get('/customer/details/')
+ self.assertEqual(response.status_code, 200)
+
+ def test_index(self):
+ client = Client()
+ response = client.get('/customer/index/')
+ self.assertEqual(response.status_code, 200)
+
+...you can just refer to ``self.client``, like so::
+
+ from django.test import TestCase
+
+ class SimpleTest(TestCase):
+ def test_details(self):
+ response = self.client.get('/customer/details/')
+ self.assertEqual(response.status_code, 200)
+
+ def test_index(self):
+ response = self.client.get('/customer/index/')
+ self.assertEqual(response.status_code, 200)
+
+Customizing the test client
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. attribute:: SimpleTestCase.client_class
+
+If you want to use a different ``Client`` class (for example, a subclass
+with customized behavior), use the :attr:`~SimpleTestCase.client_class` class
+attribute::
+
+ from django.test import TestCase, Client
+
+ class MyTestClient(Client):
+ # Specialized methods for your environment...
+
+ class MyTest(TestCase):
+ client_class = MyTestClient
+
+ def test_my_stuff(self):
+ # Here self.client is an instance of MyTestClient...
+ call_some_test_code()
+
+.. _topics-testing-fixtures:
+
+Fixture loading
+~~~~~~~~~~~~~~~
+
+.. attribute:: TransactionTestCase.fixtures
+
+A test case for a database-backed Web site isn't much use if there isn't any
+data in the database. To make it easy to put test data into the database,
+Django's custom ``TransactionTestCase`` class provides a way of loading
+**fixtures**.
+
+A fixture is a collection of data that Django knows how to import into a
+database. For example, if your site has user accounts, you might set up a
+fixture of fake user accounts in order to populate your database during tests.
+
+The most straightforward way of creating a fixture is to use the
+:djadmin:`manage.py dumpdata <dumpdata>` command. This assumes you
+already have some data in your database. See the :djadmin:`dumpdata
+documentation<dumpdata>` for more details.
+
+.. note::
+
+ If you've ever run :djadmin:`manage.py migrate<migrate>`, you've
+ already used a fixture without even knowing it! When you call
+ :djadmin:`migrate` in the database for the first time, Django
+ installs a fixture called ``initial_data``. This gives you a way
+ of populating a new database with any initial data, such as a
+ default set of categories.
+
+ Fixtures with other names can always be installed manually using
+ the :djadmin:`manage.py loaddata<loaddata>` command.
+
+.. admonition:: Initial SQL data and testing
+
+ Django provides a second way to insert initial data into models --
+ the :ref:`custom SQL hook <initial-sql>`. However, this technique
+ *cannot* be used to provide initial data for testing purposes.
+ Django's test framework flushes the contents of the test database
+ after each test; as a result, any data added using the custom SQL
+ hook will be lost.
+
+Once you've created a fixture and placed it in a ``fixtures`` directory in one
+of your :setting:`INSTALLED_APPS`, you can use it in your unit tests by
+specifying a ``fixtures`` class attribute on your :class:`django.test.TestCase`
+subclass::
+
+ from django.test import TestCase
+ from myapp.models import Animal
+
+ class AnimalTestCase(TestCase):
+ fixtures = ['mammals.json', 'birds']
+
+ def setUp(self):
+ # Test definitions as before.
+ call_setup_methods()
+
+ def testFluffyAnimals(self):
+ # A test that uses the fixtures.
+ call_some_test_code()
+
+Here's specifically what will happen:
+
+* At the start of each test case, before ``setUp()`` is run, Django will
+ flush the database, returning the database to the state it was in
+ directly after :djadmin:`migrate` was called.
+
+* Then, all the named fixtures are installed. In this example, Django will
+ install any JSON fixture named ``mammals``, followed by any fixture named
+ ``birds``. See the :djadmin:`loaddata` documentation for more
+ details on defining and installing fixtures.
+
+This flush/load procedure is repeated for each test in the test case, so you
+can be certain that the outcome of a test will not be affected by another test,
+or by the order of test execution.
+
+By default, fixtures are only loaded into the ``default`` database. If you are
+using multiple databases and set :attr:`multi_db=True
+<TransactionTestCase.multi_db>`, fixtures will be loaded into all databases.
+
+URLconf configuration
+~~~~~~~~~~~~~~~~~~~~~
+
+.. attribute:: SimpleTestCase.urls
+
+If your application provides views, you may want to include tests that use the
+test client to exercise those views. However, an end user is free to deploy the
+views in your application at any URL of their choosing. This means that your
+tests can't rely upon the fact that your views will be available at a
+particular URL.
+
+In order to provide a reliable URL space for your test,
+``django.test.*TestCase`` classes provide the ability to customize the URLconf
+configuration for the duration of the execution of a test suite. If your
+``*TestCase`` instance defines an ``urls`` attribute, the ``*TestCase`` will use
+the value of that attribute as the :setting:`ROOT_URLCONF` for the duration
+of that test.
+
+For example::
+
+ from django.test import TestCase
+
+ class TestMyViews(TestCase):
+ urls = 'myapp.test_urls'
+
+ def testIndexPageView(self):
+ # Here you'd test your view using ``Client``.
+ call_some_test_code()
+
+This test case will use the contents of ``myapp.test_urls`` as the
+URLconf for the duration of the test case.
+
+.. _emptying-test-outbox:
+
+Multi-database support
+~~~~~~~~~~~~~~~~~~~~~~
+
+.. attribute:: TransactionTestCase.multi_db
+
+Django sets up a test database corresponding to every database that is
+defined in the :setting:`DATABASES` definition in your settings
+file. However, a big part of the time taken to run a Django TestCase
+is consumed by the call to ``flush`` that ensures that you have a
+clean database at the start of each test run. If you have multiple
+databases, multiple flushes are required (one for each database),
+which can be a time consuming activity -- especially if your tests
+don't need to test multi-database activity.
+
+As an optimization, Django only flushes the ``default`` database at
+the start of each test run. If your setup contains multiple databases,
+and you have a test that requires every database to be clean, you can
+use the ``multi_db`` attribute on the test suite to request a full
+flush.
+
+For example::
+
+ class TestMyViews(TestCase):
+ multi_db = True
+
+ def testIndexPageView(self):
+ call_some_test_code()
+
+This test case will flush *all* the test databases before running
+``testIndexPageView``.
+
+The ``multi_db`` flag also affects into which databases the
+attr:`TransactionTestCase.fixtures` are loaded. By default (when
+``multi_db=False``), fixtures are only loaded into the ``default`` database.
+If ``multi_db=True``, fixtures are loaded into all databases.
+
+.. _overriding-settings:
+
+Overriding settings
+~~~~~~~~~~~~~~~~~~~
+
+.. method:: SimpleTestCase.settings
+
+For testing purposes it's often useful to change a setting temporarily and
+revert to the original value after running the testing code. For this use case
+Django provides a standard Python context manager (see :pep:`343`) called
+:meth:`~django.test.SimpleTestCase.settings`, which can be used like this::
+
+ from django.test import TestCase
+
+ class LoginTestCase(TestCase):
+
+ def test_login(self):
+
+ # First check for the default behavior
+ response = self.client.get('/sekrit/')
+ self.assertRedirects(response, '/accounts/login/?next=/sekrit/')
+
+ # Then override the LOGIN_URL setting
+ with self.settings(LOGIN_URL='/other/login/'):
+ response = self.client.get('/sekrit/')
+ self.assertRedirects(response, '/other/login/?next=/sekrit/')
+
+This example will override the :setting:`LOGIN_URL` setting for the code
+in the ``with`` block and reset its value to the previous state afterwards.
+
+.. method:: SimpleTestCase.modify_settings
+
+.. versionadded:: 1.7
+
+It can prove unwieldy to redefine settings that contain a list of values. In
+practice, adding or removing values is often sufficient. The
+:meth:`~django.test.SimpleTestCase.modify_settings` context manager makes it
+easy::
+
+ from django.test import TestCase
+
+ class MiddlewareTestCase(TestCase):
+
+ def test_cache_middleware(self):
+ with self.modify_settings(MIDDLEWARE_CLASSES={
+ 'append': 'django.middleware.cache.FetchFromCacheMiddleware',
+ 'prepend': 'django.middleware.cache.UpdateCacheMiddleware',
+ 'remove': [
+ 'django.contrib.sessions.middleware.SessionMiddleware',
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
+ 'django.contrib.messages.middleware.MessageMiddleware',
+ ],
+ }):
+ response = self.client.get('/')
+ # ...
+
+For each action, you can supply either a list of values or a string. When the
+value already exists in the list, ``append`` and ``prepend`` have no effect;
+neither does ``remove`` when the value doesn't exist.
+
+.. function:: override_settings
+
+In case you want to override a setting for a test method, Django provides the
+:func:`~django.test.override_settings` decorator (see :pep:`318`). It's used
+like this::
+
+ from django.test import TestCase, override_settings
+
+ class LoginTestCase(TestCase):
+
+ @override_settings(LOGIN_URL='/other/login/')
+ def test_login(self):
+ response = self.client.get('/sekrit/')
+ self.assertRedirects(response, '/other/login/?next=/sekrit/')
+
+The decorator can also be applied to :class:`~django.test.TestCase` classes::
+
+ from django.test import TestCase, override_settings
+
+ @override_settings(LOGIN_URL='/other/login/')
+ class LoginTestCase(TestCase):
+
+ def test_login(self):
+ response = self.client.get('/sekrit/')
+ self.assertRedirects(response, '/other/login/?next=/sekrit/')
+
+.. versionchanged:: 1.7
+
+ Previously, ``override_settings`` was imported from ``django.test.utils``.
+
+.. function:: modify_settings
+
+.. versionadded:: 1.7
+
+Likewise, Django provides the :func:`~django.test.modify_settings`
+decorator::
+
+ from django.test import TestCase, modify_settings
+
+ class MiddlewareTestCase(TestCase):
+
+ @modify_settings(MIDDLEWARE_CLASSES={
+ 'append': 'django.middleware.cache.FetchFromCacheMiddleware',
+ 'prepend': 'django.middleware.cache.UpdateCacheMiddleware',
+ })
+ def test_cache_middleware(self):
+ response = self.client.get('/')
+ # ...
+
+The decorator can also be applied to test case classes::
+
+ from django.test import TestCase, modify_settings
+
+ @modify_settings(MIDDLEWARE_CLASSES={
+ 'append': 'django.middleware.cache.FetchFromCacheMiddleware',
+ 'prepend': 'django.middleware.cache.UpdateCacheMiddleware',
+ })
+ class MiddlewareTestCase(TestCase):
+
+ def test_cache_middleware(self):
+ response = self.client.get('/')
+ # ...
+
+.. note::
+
+ When given a class, these decorators modify the class directly and return
+ it; they don't create and return a modified copy of it. So if you try to
+ tweak the above examples to assign the return value to a different name
+ than ``LoginTestCase`` or ``MiddlewareTestCase``, you may be surprised to
+ find that the original test case classes are still equally affected by the
+ decorator. For a given class, :func:`~django.test.modify_settings` is
+ always applied after :func:`~django.test.override_settings`.
+
+.. warning::
+
+ The settings file contains some settings that are only consulted during
+ initialization of Django internals. If you change them with
+ ``override_settings``, the setting is changed if you access it via the
+ ``django.conf.settings`` module, however, Django's internals access it
+ differently. Effectively, using :func:`~django.test.override_settings` or
+ :func:`~django.test.modify_settings` with these settings is probably not
+ going to do what you expect it to do.
+
+ We do not recommend altering the :setting:`DATABASES` setting. Altering
+ the :setting:`CACHES` setting is possible, but a bit tricky if you are
+ using internals that make using of caching, like
+ :mod:`django.contrib.sessions`. For example, you will have to reinitialize
+ the session backend in a test that uses cached sessions and overrides
+ :setting:`CACHES`.
+
+You can also simulate the absence of a setting by deleting it after settings
+have been overridden, like this::
+
+ @override_settings()
+ def test_something(self):
+ del settings.LOGIN_URL
+ ...
+
+When overriding settings, make sure to handle the cases in which your app's
+code uses a cache or similar feature that retains state even if the setting is
+changed. Django provides the :data:`django.test.signals.setting_changed`
+signal that lets you register callbacks to clean up and otherwise reset state
+when settings are changed.
+
+Django itself uses this signal to reset various data:
+
+================================ ========================
+Overridden settings Data reset
+================================ ========================
+USE_TZ, TIME_ZONE Databases timezone
+TEMPLATE_CONTEXT_PROCESSORS Context processors cache
+TEMPLATE_LOADERS Template loaders cache
+SERIALIZATION_MODULES Serializers cache
+LOCALE_PATHS, LANGUAGE_CODE Default translation and loaded translations
+MEDIA_ROOT, DEFAULT_FILE_STORAGE Default file storage
+================================ ========================
+
+Emptying the test outbox
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you use any of Django's custom ``TestCase`` classes, the test runner will
+clear the contents of the test email outbox at the start of each test case.
+
+For more detail on email services during tests, see `Email services`_ below.
+
+.. _assertions:
+
+Assertions
+~~~~~~~~~~
+
+As Python's normal :class:`unittest.TestCase` class implements assertion methods
+such as :meth:`~unittest.TestCase.assertTrue` and
+:meth:`~unittest.TestCase.assertEqual`, Django's custom :class:`TestCase` class
+provides a number of custom assertion methods that are useful for testing Web
+applications:
+
+The failure messages given by most of these assertion methods can be customized
+with the ``msg_prefix`` argument. This string will be prefixed to any failure
+message generated by the assertion. This allows you to provide additional
+details that may help you to identify the location and cause of an failure in
+your test suite.
+
+.. method:: SimpleTestCase.assertRaisesMessage(expected_exception, expected_message, callable_obj=None, *args, **kwargs)
+
+ Asserts that execution of callable ``callable_obj`` raised the
+ ``expected_exception`` exception and that such exception has an
+ ``expected_message`` representation. Any other outcome is reported as a
+ failure. Similar to unittest's :meth:`~unittest.TestCase.assertRaisesRegexp`
+ with the difference that ``expected_message`` isn't a regular expression.
+
+.. method:: SimpleTestCase.assertFieldOutput(self, fieldclass, valid, invalid, field_args=None, field_kwargs=None, empty_value=u'')
+
+ Asserts that a form field behaves correctly with various inputs.
+
+ :param fieldclass: the class of the field to be tested.
+ :param valid: a dictionary mapping valid inputs to their expected cleaned
+ values.
+ :param invalid: a dictionary mapping invalid inputs to one or more raised
+ error messages.
+ :param field_args: the args passed to instantiate the field.
+ :param field_kwargs: the kwargs passed to instantiate the field.
+ :param empty_value: the expected clean output for inputs in ``empty_values``.
+
+ For example, the following code tests that an ``EmailField`` accepts
+ "a@a.com" as a valid email address, but rejects "aaa" with a reasonable
+ error message::
+
+ self.assertFieldOutput(EmailField, {'a@a.com': 'a@a.com'}, {'aaa': [u'Enter a valid email address.']})
+
+.. method:: SimpleTestCase.assertFormError(response, form, field, errors, msg_prefix='')
+
+ Asserts that a field on a form raises the provided list of errors when
+ rendered on the form.
+
+ ``form`` is the name the ``Form`` instance was given in the template
+ context.
+
+ ``field`` is the name of the field on the form to check. If ``field``
+ has a value of ``None``, non-field errors (errors you can access via
+ ``form.non_field_errors()``) will be checked.
+
+ ``errors`` is an error string, or a list of error strings, that are
+ expected as a result of form validation.
+
+.. method:: SimpleTestCase.assertFormsetError(response, formset, form_index, field, errors, msg_prefix='')
+
+ .. versionadded:: 1.6
+
+ Asserts that the ``formset`` raises the provided list of errors when
+ rendered.
+
+ ``formset`` is the name the ``Formset`` instance was given in the template
+ context.
+
+ ``form_index`` is the number of the form within the ``Formset``. If
+ ``form_index`` has a value of ``None``, non-form errors (errors you can
+ access via ``formset.non_form_errors()``) will be checked.
+
+ ``field`` is the name of the field on the form to check. If ``field``
+ has a value of ``None``, non-field errors (errors you can access via
+ ``form.non_field_errors()``) will be checked.
+
+ ``errors`` is an error string, or a list of error strings, that are
+ expected as a result of form validation.
+
+.. method:: SimpleTestCase.assertContains(response, text, count=None, status_code=200, msg_prefix='', html=False)
+
+ Asserts that a ``Response`` instance produced the given ``status_code`` and
+ that ``text`` appears in the content of the response. If ``count`` is
+ provided, ``text`` must occur exactly ``count`` times in the response.
+
+ Set ``html`` to ``True`` to handle ``text`` as HTML. The comparison with
+ the response content will be based on HTML semantics instead of
+ character-by-character equality. Whitespace is ignored in most cases,
+ attribute ordering is not significant. See
+ :meth:`~SimpleTestCase.assertHTMLEqual` for more details.
+
+.. method:: SimpleTestCase.assertNotContains(response, text, status_code=200, msg_prefix='', html=False)
+
+ Asserts that a ``Response`` instance produced the given ``status_code`` and
+ that ``text`` does not appears in the content of the response.
+
+ Set ``html`` to ``True`` to handle ``text`` as HTML. The comparison with
+ the response content will be based on HTML semantics instead of
+ character-by-character equality. Whitespace is ignored in most cases,
+ attribute ordering is not significant. See
+ :meth:`~SimpleTestCase.assertHTMLEqual` for more details.
+
+.. method:: SimpleTestCase.assertTemplateUsed(response, template_name, msg_prefix='')
+
+ Asserts that the template with the given name was used in rendering the
+ response.
+
+ The name is a string such as ``'admin/index.html'``.
+
+ You can use this as a context manager, like this::
+
+ with self.assertTemplateUsed('index.html'):
+ render_to_string('index.html')
+ with self.assertTemplateUsed(template_name='index.html'):
+ render_to_string('index.html')
+
+.. method:: SimpleTestCase.assertTemplateNotUsed(response, template_name, msg_prefix='')
+
+ Asserts that the template with the given name was *not* used in rendering
+ the response.
+
+ You can use this as a context manager in the same way as
+ :meth:`~SimpleTestCase.assertTemplateUsed`.
+
+.. method:: SimpleTestCase.assertRedirects(response, expected_url, status_code=302, target_status_code=200, msg_prefix='', fetch_redirect_response=True)
+
+ Asserts that the response return a ``status_code`` redirect status, it
+ redirected to ``expected_url`` (including any GET data), and the final
+ page was received with ``target_status_code``.
+
+ If your request used the ``follow`` argument, the ``expected_url`` and
+ ``target_status_code`` will be the url and status code for the final
+ point of the redirect chain.
+
+ .. versionadded:: 1.7
+
+ If ``fetch_redirect_response`` is ``False``, the final page won't be
+ loaded. Since the test client can't fetch externals URLs, this is
+ particularly useful if ``expected_url`` isn't part of your Django app.
+
+ .. versionadded:: 1.7
+
+ Scheme is handled correctly when making comparisons between two URLs. If
+ there isn't any scheme specified in the location where we are redirected to,
+ the original request's scheme is used. If present, the scheme in
+ ``expected_url`` is the one used to make the comparisons to.
+
+.. method:: SimpleTestCase.assertHTMLEqual(html1, html2, msg=None)
+
+ Asserts that the strings ``html1`` and ``html2`` are equal. The comparison
+ is based on HTML semantics. The comparison takes following things into
+ account:
+
+ * Whitespace before and after HTML tags is ignored.
+ * All types of whitespace are considered equivalent.
+ * All open tags are closed implicitly, e.g. when a surrounding tag is
+ closed or the HTML document ends.
+ * Empty tags are equivalent to their self-closing version.
+ * The ordering of attributes of an HTML element is not significant.
+ * Attributes without an argument are equal to attributes that equal in
+ name and value (see the examples).
+
+ The following examples are valid tests and don't raise any
+ ``AssertionError``::
+
+ self.assertHTMLEqual('<p>Hello <b>world!</p>',
+ '''<p>
+ Hello <b>world! <b/>
+ </p>''')
+ self.assertHTMLEqual(
+ '<input type="checkbox" checked="checked" id="id_accept_terms" />',
+ '<input id="id_accept_terms" type='checkbox' checked>')
+
+ ``html1`` and ``html2`` must be valid HTML. An ``AssertionError`` will be
+ raised if one of them cannot be parsed.
+
+ Output in case of error can be customized with the ``msg`` argument.
+
+.. method:: SimpleTestCase.assertHTMLNotEqual(html1, html2, msg=None)
+
+ Asserts that the strings ``html1`` and ``html2`` are *not* equal. The
+ comparison is based on HTML semantics. See
+ :meth:`~SimpleTestCase.assertHTMLEqual` for details.
+
+ ``html1`` and ``html2`` must be valid HTML. An ``AssertionError`` will be
+ raised if one of them cannot be parsed.
+
+ Output in case of error can be customized with the ``msg`` argument.
+
+.. method:: SimpleTestCase.assertXMLEqual(xml1, xml2, msg=None)
+
+ Asserts that the strings ``xml1`` and ``xml2`` are equal. The
+ comparison is based on XML semantics. Similarly to
+ :meth:`~SimpleTestCase.assertHTMLEqual`, the comparison is
+ made on parsed content, hence only semantic differences are considered, not
+ syntax differences. When unvalid XML is passed in any parameter, an
+ ``AssertionError`` is always raised, even if both string are identical.
+
+ Output in case of error can be customized with the ``msg`` argument.
+
+.. method:: SimpleTestCase.assertXMLNotEqual(xml1, xml2, msg=None)
+
+ Asserts that the strings ``xml1`` and ``xml2`` are *not* equal. The
+ comparison is based on XML semantics. See
+ :meth:`~SimpleTestCase.assertXMLEqual` for details.
+
+ Output in case of error can be customized with the ``msg`` argument.
+
+.. method:: SimpleTestCase.assertInHTML(needle, haystack, count=None, msg_prefix='')
+
+ Asserts that the HTML fragment ``needle`` is contained in the ``haystack`` one.
+
+ If the ``count`` integer argument is specified, then additionally the number
+ of ``needle`` occurrences will be strictly verified.
+
+ Whitespace in most cases is ignored, and attribute ordering is not
+ significant. The passed-in arguments must be valid HTML.
+
+.. method:: SimpleTestCase.assertJSONEqual(raw, expected_data, msg=None)
+
+ Asserts that the JSON fragments ``raw`` and ``expected_data`` are equal.
+ Usual JSON non-significant whitespace rules apply as the heavyweight is
+ delegated to the :mod:`json` library.
+
+ Output in case of error can be customized with the ``msg`` argument.
+
+.. method:: TransactionTestCase.assertQuerysetEqual(qs, values, transform=repr, ordered=True)
+
+ Asserts that a queryset ``qs`` returns a particular list of values ``values``.
+
+ The comparison of the contents of ``qs`` and ``values`` is performed using
+ the function ``transform``; by default, this means that the ``repr()`` of
+ each value is compared. Any other callable can be used if ``repr()`` doesn't
+ provide a unique or helpful comparison.
+
+ By default, the comparison is also ordering dependent. If ``qs`` doesn't
+ provide an implicit ordering, you can set the ``ordered`` parameter to
+ ``False``, which turns the comparison into a Python set comparison.
+
+ .. versionchanged:: 1.6
+
+ The method now checks for undefined order and raises ``ValueError``
+ if undefined order is spotted. The ordering is seen as undefined if
+ the given ``qs`` isn't ordered and the comparison is against more
+ than one ordered values.
+
+.. method:: TransactionTestCase.assertNumQueries(num, func, *args, **kwargs)
+
+ Asserts that when ``func`` is called with ``*args`` and ``**kwargs`` that
+ ``num`` database queries are executed.
+
+ If a ``"using"`` key is present in ``kwargs`` it is used as the database
+ alias for which to check the number of queries. If you wish to call a
+ function with a ``using`` parameter you can do it by wrapping the call with
+ a ``lambda`` to add an extra parameter::
+
+ self.assertNumQueries(7, lambda: my_function(using=7))
+
+ You can also use this as a context manager::
+
+ with self.assertNumQueries(2):
+ Person.objects.create(name="Aaron")
+ Person.objects.create(name="Daniel")
+
+.. _topics-testing-email:
+
+Email services
+--------------
+
+If any of your Django views send email using :doc:`Django's email
+functionality </topics/email>`, you probably don't want to send email each time
+you run a test using that view. For this reason, Django's test runner
+automatically redirects all Django-sent email to a dummy outbox. This lets you
+test every aspect of sending email -- from the number of messages sent to the
+contents of each message -- without actually sending the messages.
+
+The test runner accomplishes this by transparently replacing the normal
+email backend with a testing backend.
+(Don't worry -- this has no effect on any other email senders outside of
+Django, such as your machine's mail server, if you're running one.)
+
+.. currentmodule:: django.core.mail
+
+.. data:: django.core.mail.outbox
+
+During test running, each outgoing email is saved in
+``django.core.mail.outbox``. This is a simple list of all
+:class:`~django.core.mail.EmailMessage` instances that have been sent.
+The ``outbox`` attribute is a special attribute that is created *only* when
+the ``locmem`` email backend is used. It doesn't normally exist as part of the
+:mod:`django.core.mail` module and you can't import it directly. The code
+below shows how to access this attribute correctly.
+
+Here's an example test that examines ``django.core.mail.outbox`` for length
+and contents::
+
+ from django.core import mail
+ from django.test import TestCase
+
+ class EmailTest(TestCase):
+ def test_send_email(self):
+ # Send message.
+ mail.send_mail('Subject here', 'Here is the message.',
+ 'from@example.com', ['to@example.com'],
+ fail_silently=False)
+
+ # Test that one message has been sent.
+ self.assertEqual(len(mail.outbox), 1)
+
+ # Verify that the subject of the first message is correct.
+ self.assertEqual(mail.outbox[0].subject, 'Subject here')
+
+As noted :ref:`previously <emptying-test-outbox>`, the test outbox is emptied
+at the start of every test in a Django ``*TestCase``. To empty the outbox
+manually, assign the empty list to ``mail.outbox``::
+
+ from django.core import mail
+
+ # Empty the test outbox
+ mail.outbox = []
+
+.. _skipping-tests:
+
+Skipping tests
+--------------
+
+.. currentmodule:: django.test
+
+The unittest library provides the :func:`@skipIf <unittest.skipIf>` and
+:func:`@skipUnless <unittest.skipUnless>` decorators to allow you to skip tests
+if you know ahead of time that those tests are going to fail under certain
+conditions.
+
+For example, if your test requires a particular optional library in order to
+succeed, you could decorate the test case with :func:`@skipIf
+<unittest.skipIf>`. Then, the test runner will report that the test wasn't
+executed and why, instead of failing the test or omitting the test altogether.
+
+To supplement these test skipping behaviors, Django provides two
+additional skip decorators. Instead of testing a generic boolean,
+these decorators check the capabilities of the database, and skip the
+test if the database doesn't support a specific named feature.
+
+The decorators use a string identifier to describe database features.
+This string corresponds to attributes of the database connection
+features class. See ``django.db.backends.BaseDatabaseFeatures``
+class for a full list of database features that can be used as a basis
+for skipping tests.
+
+.. function:: skipIfDBFeature(feature_name_string)
+
+Skip the decorated test or ``TestCase`` if the named database feature is
+supported.
+
+For example, the following test will not be executed if the database
+supports transactions (e.g., it would *not* run under PostgreSQL, but
+it would under MySQL with MyISAM tables)::
+
+ class MyTests(TestCase):
+ @skipIfDBFeature('supports_transactions')
+ def test_transaction_behavior(self):
+ # ... conditional test code
+
+.. versionchanged:: 1.7
+
+ ``skipIfDBFeature`` can now be used to decorate a ``TestCase`` class.
+
+.. function:: skipUnlessDBFeature(feature_name_string)
+
+Skip the decorated test or ``TestCase`` if the named database feature is *not*
+supported.
+
+For example, the following test will only be executed if the database
+supports transactions (e.g., it would run under PostgreSQL, but *not*
+under MySQL with MyISAM tables)::
+
+ class MyTests(TestCase):
+ @skipUnlessDBFeature('supports_transactions')
+ def test_transaction_behavior(self):
+ # ... conditional test code
+
+.. versionchanged:: 1.7
+
+ ``skipUnlessDBFeature`` can now be used to decorate a ``TestCase`` class.