Refs #2333 - Added documentation for the test Client, and removed a stray import.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@3711 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Russell Keith-Magee 2006-09-03 02:44:15 +00:00
parent 5a1d560fb3
commit 8192a808bd
2 changed files with 179 additions and 25 deletions

View File

@ -60,7 +60,6 @@ from django.conf import settings
from django.template.context import Context, RequestContext, ContextPopException
from django.utils.functional import curry
from django.utils.text import smart_split
from django.dispatch import dispatcher
__all__ = ('Template', 'Context', 'RequestContext', 'compile_string')

View File

@ -159,20 +159,166 @@ Again, remember that you can use both systems side-by-side (even in the same
app). In the end, most projects will eventually end up using both; each shines
in different circumstances.
Testing utilities
=================
Testing Tools
=============
To assist in testing various features of your application, Django provides
tools that can be used to establish tests and test conditions.
* `Test Client`_
* Fixtures_
Test Client
-----------
A dummy browser; instruments the template generation process...
The Test Client is a simple dummy browser. It allows you to simulate
GET and POST requests on a URL, and observe the response that is received.
This allows you to test that the correct view is executed for a given URL,
and that the view constructs the correct response.
As the response is generated, the Test Client gathers details on the
Template and Context objects that were used to generate the response. These
Templates and Contexts are then provided as part of the response, and can be
used as test conditions.
.. admonition:: Test Client vs Browser Automation?
The Test Client is not intended as a replacement for Twill_, Selenium_,
or other browser automation frameworks - it is intended to allow
testing of the contexts and templates produced by a view,
rather than the HTML rendered to the end-user.
A comprehensive test suite should use a combination of both: Test Client
tests to establish that the correct view is being called and that
the view is collecting the correct context data, and Browser Automation
tests to check that user interface behaves as expected.
.. _Twill: http://twill.idyll.org/
.. _Selenium: http://www.openqa.org/selenium/
The Test Client is stateful; if a cookie is returned as part of a response,
that cookie is provided as part of the next request. Expiry policies for these
cookies are not followed; if you want a cookie to expire, either delete it
manually from ``client.cookies``, or create a new Client instance (which will
effectively delete all cookies).
Making requests
~~~~~~~~~~~~~~~
Creating an instance of ``Client`` (``django.test.client.Client``) requires
no arguments at time of construction. Once constructed, the following methods
can be invoked on the ``Client`` instance.
``get(path, data={}):``
Make a GET request on the provided ``path``. The key-value pairs in the
data dictionary will be 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::
http://yoursite.com/customers/details/?name='fred'&age=7
``post(path, data={}):``
Make a POST request on the provided ``path``. The key-value pairs in the
data dictionary will be used to create the POST data payload. This payload
will be transmitted with the mimetype ```multipart/form-data``.
However 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. The Test Client will populate the two POST fields (i.e.,
``field`` and ``field_file``) required by FileField. For example::
c = Client()
f = open('wishlist.doc')
c.post('/customers/wishes/', {'name':'fred', 'attachment':f})
f.close()
will result in the evaluation of a POST request on ``/customers/wishes/``,
with a POST dictionary that contains `name`, `attachment` (containing the
file name), and `attachment_file` (containing the file data). Note that you
need to manually close the file after it has been provided to the POST.
``login(path, username, password):``
In a production site, it is likely that some views will be protected with
the @login_required URL provided by ``django.contrib.auth``. Interacting
with a URL that has been login protected is a slightly complex operation,
so the Test Client provides a simple URL to automate the login process. A
call to ``login()`` stimulates the series of GET and POST calls required
to log a user into a @login_required protected URL.
If login is possible, the final return value of ``login()`` is the response
that is generated by issuing a GET request on the protected URL. If login
is not possible, ``login()`` returns False.
Note that since the test suite will be executed using the test database,
which contains no users by default. As a result, logins for your production
site will not work. You will need to create users as part of the test suite
to be able to test logins to your application.
Testing Responses
~~~~~~~~~~~~~~~~~
The ``get()``, ``post()`` and ``login()`` methods all return a Response
object. This Response object has the following properties that can be used
for testing purposes:
``status_code``
The HTTP status of the response. See RFC2616_ for a full list of HTTP status
codes.
.. _RFC2616: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
``content``
The body of the response. The is the final page content as rendered by
the view, or any error message (such as the URL for a 302 redirect).
``template``
The Template instance that was used to render the final content.
Testing ``template.name`` can be particularly useful; if the
template was loaded from a file, ``name`` will be the file name that
was loaded.
If multiple templates were rendered, (e.g., if one template includes
another template),``template`` will be a list of Template objects, in
the order in which they were rendered.
``context``
The Context that was used to render the template that produced the
response content.
As with ``template``, if multiple templates were rendered ``context``
will be a list of Context objects, stored in the order in which they
were rendered.
The following is a simple unit test using the Test Client::
import unittest
from django.test.client import Client
class SimpleTest(unittest.TestCase):
def setUp(self):
# Every test needs a client
self.client = Client()
def test_details(self):
response = self.client.get('/customer/details/')
self.failUnlessEqual(response.status_code, 200)
self.failUnlessEqual(len(response.context['customers']), 5)
Fixtures
--------
Feature still to come...
Running tests
=============
@ -245,11 +391,13 @@ When you run ``./manage.py test``, Django looks at the ``TEST_RUNNER``
setting to determine what to do. By default, ``TEST_RUNNER`` points to ``django.test.simple.run_tests``. This method defines the default Django
testing behaviour. This behaviour involves:
#. Performing global pre-test setup
#. Creating the test database
#. Running ``syncdb`` to install models and initial data into the test database
#. Looking for Unit Tests and Doctests in ``models.py`` and ``tests.py`` file for each installed application
#. Running the Unit Tests and Doctests that are found
#. Destroying the test database.
#. Performing global post-test teardown
If you define your own test runner method and point ``TEST_RUNNER``
at that method, Django will execute your test runner whenever you run
@ -263,14 +411,13 @@ can call it anything you want. The only requirement is that it accept two
arguments:
``run_tests(module_list, verbosity=1)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The module list is the list of Python modules that contain the models to be
tested. This is the same format returned by ``django.db.models.get_apps()``
The module list is the list of Python modules that contain the models to be
tested. This is the same format returned by ``django.db.models.get_apps()``
Verbosity determines the amount of notification and debug information that
will be printed to the console; '0' is no output, '1' is normal output,
and `2` is verbose output.
Verbosity determines the amount of notification and debug information that
will be printed to the console; '0' is no output, '1' is normal output,
and `2` is verbose output.
Testing utilities
-----------------
@ -278,26 +425,34 @@ Testing utilities
To assist in the creation of your own test runner, Django provides
a number of utility methods in the ``django.test.utils`` module.
``setup_test_environment()``
Performs any global pre-test setup, such as the installing the
instrumentation of the template rendering system.
``teardown_test_environment()``
Performs any global post-test teardown, such as removing the instrumentation
of the template rendering system.
``create_test_db(verbosity=1, autoclobber=False)``:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Creates a new test database, and run ``syncdb`` against it.
Creates a new test database, and run ``syncdb`` against it.
``verbosity`` has the same behaviour as in the test runner.
``verbosity`` has the same behaviour as in the test runner.
``Autoclobber`` describes the behavior that will occur if a database with
the same name as the test database is discovered. If ``autoclobber`` is False,
the user will be asked to approve destroying the existing database. ``sys.exit``
is called if the user does not approve. If autoclobber is ``True``, the database
will be destroyed without consulting the user.
``Autoclobber`` describes the behavior that will occur if a database with
the same name as the test database is discovered. If ``autoclobber`` is False,
the user will be asked to approve destroying the existing database. ``sys.exit``
is called if the user does not approve. If autoclobber is ``True``, the database
will be destroyed without consulting the user.
``create_test_db()`` has the side effect of modifying
``settings.DATABASE_NAME`` to match the name of the test database.
``create_test_db()`` has the side effect of modifying
``settings.DATABASE_NAME`` to match the name of the test database.
``destroy_test_db(old_database_name, verbosity=1)``:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Destroys the database with the name ``settings.DATABASE_NAME`` matching,
and restores the value of ``settings.DATABASE_NAME`` to the provided name.
Destroys the database with the name ``settings.DATABASE_NAME`` matching,
and restores the value of ``settings.DATABASE_NAME`` to the provided name.
``verbosity`` has the same behaviour as in the test runner.
``verbosity`` has the same behaviour as in the test runner.