Author: gwilson
Date: 2008-08-25 19:52:55 -0500 (Mon, 25 Aug 2008)
New Revision: 8567
Modified:
django/trunk/docs/topics/testing.txt
Log:
A few fixes for the testing documentation:
* Removed an extra semicolon that was preventing the rendering of a Sphinx
class directive for the `Client()` class.
* Indented `Client` class's methods.
* Added linebreaks after attribute directives of `Response` class so Sphinx
rendenders them correctly.
* Removed trailing whitespace.
Modified: django/trunk/docs/topics/testing.txt
===================================================================
--- django/trunk/docs/topics/testing.txt 2008-08-26 00:46:30 UTC (rev
8566)
+++ django/trunk/docs/topics/testing.txt 2008-08-26 00:52:55 UTC (rev
8567)
@@ -131,21 +131,20 @@
def speak(self):
return 'The %s says "%s"' % (self.name, self.sound)
-When you :ref:`run your tests <running-tests>`, the test runner will find this
docstring, notice
-that portions of it look like an interactive Python session, and execute those
-lines while checking that the results match.
+When you :ref:`run your tests <running-tests>`, the test runner will find this
+docstring, notice that portions of it look like an interactive Python session,
+and execute those lines while checking that the results match.
-In the case of model tests, note that the test runner takes care of
-creating its own test database. That is, any test that accesses a
-database -- by creating and saving model instances, for example --
-will not affect your production database. Each doctest begins with a
-"blank slate" -- a fresh database containing an empty table for each
-model. (See the section on fixtures, below, for more on this.) Note
-that to use this feature, the database user Django is connecting as
-must have ``CREATE DATABASE`` rights.
+In the case of model tests, note that the test runner takes care of creating
+its own test database. That is, any test that accesses a database -- by
+creating and saving model instances, for example -- will not affect your
+production database. Each doctest begins with a "blank slate" -- a fresh
+database containing an empty table for each model. (See the section on
+fixtures, below, for more on this.) Note that to use this feature, the database
+user Django is connecting as must have ``CREATE DATABASE`` rights.
For more details about how doctest works, see the `standard library
-documentation for doctest`_
+documentation for doctest`_.
.. _doctest: http://docs.python.org/lib/module-doctest.html
.. _standard library documentation for doctest: doctest_
@@ -182,17 +181,17 @@
self.assertEquals(self.lion.speak(), 'The lion says "roar"')
self.assertEquals(self.cat.speak(), 'The cat says "meow"')
-When you :ref:`run your tests <running-tests>`, the default behavior of the
test utility is
-to find all the test cases (that is, subclasses of ``unittest.TestCase``)
-in ``models.py`` and ``tests.py``, automatically build a test suite out of
-those test cases, and run that suite.
+When you :ref:`run your tests <running-tests>`, the default behavior of the
+test utility is to find all the test cases (that is, subclasses of
+``unittest.TestCase``) in ``models.py`` and ``tests.py``, automatically build a
+test suite out of those test cases, and run that suite.
In the Django development version, there is a second way to define the test
suite for a module: if you define a function called ``suite()`` in either
``models.py`` or ``tests.py``, the Django test runner will use that function
-to construct the test suite for that module. This follows the
-`suggested organization`_ for unit tests. See the Python documentation for
-more details on how to construct a complex test suite.
+to construct the test suite for that module. This follows the `suggested
+organization`_ for unit tests. See the Python documentation for more details on
+how to construct a complex test suite.
For more details about ``unittest``, see the `standard library unittest
documentation`_.
@@ -242,7 +241,8 @@
Running tests
=============
-Once you've written tests, run them using your project's ``manage.py``
utility::
+Once you've written tests, run them using your project's ``manage.py``
+utility::
$ ./manage.py test
@@ -273,18 +273,18 @@
The test database
-----------------
-Tests that require a database (namely, model tests) will not use
-your "real" (production) database. A separate, blank database is created
-for the tests.
+Tests that require a database (namely, model tests) will not use your "real"
+(production) database. A separate, blank database is created for the tests.
Regardless of whether the tests pass or fail, the test database is destroyed
when all the tests have been executed.
-By default this test database gets its name by prepending ``test_`` to the
value
-of the :setting:`DATABASE_NAME` setting. When using the SQLite database engine
-the tests will by default use an in-memory database (i.e., the database will be
-created in memory, bypassing the filesystem entirely!). If you want to use a
-different database name, specify the :setting:`TEST_DATABASE_NAME` setting.
+By default this test database gets its name by prepending ``test_`` to the
+value of the :setting:`DATABASE_NAME` setting. When using the SQLite database
+engine the tests will by default use an in-memory database (i.e., the database
+will be created in memory, bypassing the filesystem entirely!). If you want to
+use a different database name, specify the :setting:`TEST_DATABASE_NAME`
+setting.
Aside from using a separate database, the test runner will otherwise use all of
the same database settings you have in your settings file:
@@ -466,127 +466,131 @@
~~~~~~~~~~~~~~~
Use the ``django.test.client.Client`` class to make requests. It requires no
-arguments at time of construction::
+arguments at time of construction:
.. class:: Client()
-Once you have a ``Client`` instance, you can call any of the following methods:
+ Once you have a ``Client`` instance, you can call any of the following
+ methods:
-.. method:: Client.get(path, data={})
+ .. method:: Client.get(path, data={})
- Makes a GET request on the provided ``path`` and returns a ``Response``
- object, which is documented below.
+ 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::
+ 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})
+ >>> c = Client()
+ >>> c.get('/customers/details/', {'name': 'fred', 'age': 7})
- ...will result in the evaluation of a GET request equivalent to::
+ ...will result in the evaluation of a GET request equivalent to::
- /customers/details/?name=fred&age=7
+ /customers/details/?name=fred&age=7
-.. method:: Client.post(path, data={}, content_type=MULTIPART_CONTENT)
+ .. method:: Client.post(path, data={}, content_type=MULTIPART_CONTENT)
- Makes a POST request on the provided ``path`` and returns a ``Response``
- object, which is documented below.
+ 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::
+ 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'})
+ >>> c = Client()
+ >>> c.post('/login/', {'name': 'fred', 'passwd': 'secret'})
- ...will result in the evaluation of a POST request to this URL::
+ ...will result in the evaluation of a POST request to this URL::
- /login/
+ /login/
- ...with this POST data::
+ ...with this POST data::
- name=fred&passwd=secret
+ name=fred&passwd=secret
- If you provide ``content_type`` (e.g., ``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 provide ``content_type`` (e.g., ``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
``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.
+ If you don't provide a value for ``content_type``, the values in
+ ``data`` will be transmitted with a content type of
+ ``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``::
+ 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')}
+ {'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::
+ 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()
- >>> f = open('wishlist.doc')
- >>> c.post('/customers/wishes/', {'name': 'fred', 'attachment': f})
- >>> f.close()
+ >>> c = Client()
+ >>> f = open('wishlist.doc')
+ >>> c.post('/customers/wishes/', {'name': 'fred', 'attachment': f})
+ >>> f.close()
- (The name ``attachment`` here is not relevant; use whatever name your
- file-processing code expects.)
+ (The name ``attachment`` here is not relevant; use whatever name your
+ file-processing code expects.)
- Note that you should manually close the file after it has been provided to
- ``post()``.
+ Note that you should manually close the file after it has been provided
+ to ``post()``.
-.. method:: Client.login(**credentials)
+ .. method:: Client.login(**credentials)
- **New in Django development version**
+ **New in Django development version**
- If your site uses Django's :ref:`authentication system<topics-auth>` 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.
+ If your site uses Django's :ref:`authentication system<topics-auth>`
+ 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.
+ 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::
+ 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.
+ >>> c = Client()
+ >>> c.login(username='fred', password='secret')
- 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.
+ # Now you can access a view that's only available to logged-in
users.
- ``login()`` returns ``True`` if it the credentials were accepted and login
- was successful.
+ 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.
- 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.
+ ``login()`` returns ``True`` if it the credentials were accepted and
+ login was successful.
-.. method:: Client.logout()
+ 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.
- **New in Django development version**
+ .. method:: Client.logout()
- If your site uses Django's :ref:`authentication system<topics-auth>`, the
``logout()``
- method can be used to simulate the effect of a user logging out of
- your site.
+ **New in Django development version**
- 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 AnonymousUser.
+ If your site uses Django's :ref:`authentication system<topics-auth>`,
+ 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 AnonymousUser.
+
Testing responses
~~~~~~~~~~~~~~~~~
@@ -599,37 +603,43 @@
.. class:: Response()
-.. attribute:: Response.client``
- The test client that was used to make the request that resulted in the
- response.
+ .. attribute:: client
-.. attribute:: Response.content
- The body of the response, as a string. This is the final page content as
- rendered by the view, or any error message.
+ The test client that was used to make the request that resulted in the
+ response.
-.. attribute:: Response.context
- The template ``Context`` instance that was used to render the template that
- produced the response content.
+ .. attribute:: 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.
+ The body of the response, as a string. This is the final page content
as
+ rendered by the view, or any error message.
-.. attribute:: Response.request``
- The request data that stimulated the response.
+ .. attribute:: context
-.. attribute:: Response.status_code
- The HTTP status of the response, as an integer. See RFC2616_ for a full
list
- of HTTP status codes.
+ The template ``Context`` instance that was used to render the template
that
+ produced the response content.
-.. attribute:: template
- The ``Template`` instance that was used to render the final content. 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'``.)
-
- If the rendered page used multiple templates -- e.g., using :ref:`template
- inheritance<template-inheritance>` -- then ``template`` will be a list of
``Template`` instances,
- in the order in which they were rendered.
+ If the rendered page used multiple templates, then ``context`` will be
a
+ list of ``Context`` objects, in the order in which they were rendered.
+ .. attribute:: request
+
+ The request data that stimulated the response.
+
+ .. attribute:: status_code
+
+ The HTTP status of the response, as an integer. See RFC2616_ for a full
+ list of HTTP status codes.
+
+ .. attribute:: template
+
+ The ``Template`` instance that was used to render the final content.
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'``.)
+
+ If the rendered page used multiple templates -- e.g., using
:ref:`template
+ inheritance<template-inheritance>` -- then ``template`` will be a list
of
+ ``Template`` instances, in the order in which they were rendered.
+
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']``.
@@ -669,8 +679,8 @@
.. attribute:: Client.session
- A dictionary-like object containing session information. See the
:ref:`session
- documentation<topics-http-sessions>` for full details.
+ A dictionary-like object containing session information. See the
+ :ref:`session documentation<topics-http-sessions>` for full details.
.. _Cookie module documentation: http://docs.python.org/lib/module-Cookie.html
@@ -772,9 +782,9 @@
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
-``manage.py dumpdata`` command. This assumes you already have some data in
-your database. See the :djadmin:`dumpdata documentation<dumpdata>` for more
details.
+The most straightforward way of creating a fixture is to use the ``manage.py
+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 ``manage.py syncdb``, you've already used a fixture
@@ -810,12 +820,12 @@
* 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<loaddata>` for more
details on defining
- and installing fixtures.
+ ``birds``. See the :djadmin:`loaddata documentation<loaddata>` 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.
+can be certain that the outcome of a test will not be affected by another test,
+or by the order of test execution.
URLconf configuration
~~~~~~~~~~~~~~~~~~~~~
@@ -824,23 +834,23 @@
.. attribute:: TestCase.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.
+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`` provides 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 ``ROOT_URLCONF``
-for the duration of that test.
+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 ``ROOT_URLCONF`` for the duration of that
+test.
For example::
from django.test import TestCase
-
+
class TestMyViews(TestCase):
urls = 'myapp.test_urls'
@@ -867,10 +877,10 @@
**New in Django development version**
-As Python's normal ``unittest.TestCase`` class implements assertion
-methods such as ``assertTrue`` and ``assertEquals``, Django's custom
-``TestCase`` class provides a number of custom assertion methods that are
-useful for testing Web applications:
+As Python's normal ``unittest.TestCase`` class implements assertion methods
+such as ``assertTrue`` and ``assertEquals``, Django's custom ``TestCase`` class
+provides a number of custom assertion methods that are useful for testing Web
+applications:
.. method:: TestCase.assertContains(response, text, count=None,
status_code=200)
@@ -913,8 +923,8 @@
.. method:: assertRedirects(response, expected_url, status_code=302,
target_status_code=200)
- Asserts that the response return a ``status_code`` redirect status,
- it redirected to ``expected_url`` (including any GET data), and the
subsequent
+ Asserts that the response return a ``status_code`` redirect status, it
+ redirected to ``expected_url`` (including any GET data), and the subsequent
page was received with ``target_status_code``.
E-mail services
@@ -930,21 +940,22 @@
contents of each message -- without actually sending the messages.
The test runner accomplishes this by transparently replacing the normal
-:class:`~django.core.mail.SMTPConnection` class with a different version.
(Don't
-worry -- this has no effect on any other e-mail senders outside of Django, such
-as your machine's mail server, if you're running one.)
+:class:`~django.core.mail.SMTPConnection` class with a different version.
+(Don't worry -- this has no effect on any other e-mail senders outside of
+Django, such as your machine's mail server, if you're running one.)
.. currentmodule:: django.core.mail
.. data:: django.core.mail.output
During test running, each outgoing e-mail is saved in
-``django.core.mail.outbox``. This is a simple list of all
:class:`<~django.core.mail.EmailMessage>`
-instances that have been sent. It does not exist under normal execution
-conditions, i.e., when you're not running unit tests. The outbox is created
-during test setup, along with the dummy
:class:`<~django.core.mail.SMTPConnection>`. When the test
-framework is torn down, the standard
:class:`<~django.core.mail.SMTPConnection>` class is restored, and
-the test outbox is destroyed.
+``django.core.mail.outbox``. This is a simple list of all
+:class:`<~django.core.mail.EmailMessage>` instances that have been sent.
+It does not exist under normal execution conditions, i.e., when you're not
+running unit tests. The outbox is created during test setup, along with the
+dummy :class:`<~django.core.mail.SMTPConnection>`. When the test framework is
+torn down, the standard :class:`<~django.core.mail.SMTPConnection>` class is
+restored, and the test outbox is destroyed.
Here's an example test that examines ``django.core.mail.outbox`` for length
and contents::
@@ -965,9 +976,9 @@
# 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``::
+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
@@ -1004,9 +1015,9 @@
#. Performing global post-test teardown.
If you define your own test runner method and point :setting:`TEST_RUNNER` at
-that method, Django will execute your test runner whenever you run
``./manage.py
-test``. In this way, it is possible to use any test framework that can be
-executed from Python code.
+that method, Django will execute your test runner whenever you run
+``./manage.py test``. In this way, it is possible to use any test framework
+that can be executed from Python code.
Defining a test runner
----------------------
@@ -1053,20 +1064,19 @@
.. module:: django.test.utils
:synopsis: Helpers to write custom test runners.
-To assist in the creation of your own test runner, Django provides
-a number of utility methods in the ``django.test.utils`` module.
+To assist in the creation of your own test runner, Django provides a number of
+utility methods in the ``django.test.utils`` module.
.. function:: setup_test_environment()
Performs any global pre-test setup, such as the installing the
- instrumentation of the template rendering system and setting up
- the dummy ``SMTPConnection``.
+ instrumentation of the template rendering system and setting up the dummy
+ ``SMTPConnection``.
.. function:: teardown_test_environment()
- Performs any global post-test teardown, such as removing the
- black magic hooks into the template system and restoring normal e-mail
- services.
+ Performs any global post-test teardown, such as removing the black magic
+ hooks into the template system and restoring normal e-mail services.
The creation module of the database backend (``connection.creation``) also
provides some utilities that can be useful during testing.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---