mirror of https://github.com/django/django.git
[1.5.x] Fixed #19497 -- Refactored testing docs.
Thanks Tim Graham for the review and suggestions.
d19109fd37
from master.
This commit is contained in:
parent
3aba929bcc
commit
903892be7b
|
@ -180,7 +180,11 @@ testing of Django applications:
|
|||
:doc:`Overview <ref/django-admin>` |
|
||||
:doc:`Adding custom commands <howto/custom-management-commands>`
|
||||
|
||||
* **Testing:** :doc:`Overview <topics/testing>`
|
||||
* **Testing:**
|
||||
:doc:`Introduction <topics/testing/index>` |
|
||||
:doc:`Writing and running tests <topics/testing/overview>` |
|
||||
:doc:`Advanced topics <topics/testing/advanced>` |
|
||||
:doc:`Doctests <topics/testing/doctests>`
|
||||
|
||||
* **Deployment:**
|
||||
:doc:`Overview <howto/deployment/index>` |
|
||||
|
|
|
@ -15,8 +15,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>`
|
||||
for an explanation of how to write new tests.
|
||||
testing applications. See :doc:`Testing Django applications
|
||||
</topics/testing/overview>` for an explanation of how to write new tests.
|
||||
|
||||
.. _running-unit-tests:
|
||||
|
||||
|
|
|
@ -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/>`.
|
||||
documentation on :doc:`Testing Django applications </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
|
||||
|
|
|
@ -632,7 +632,7 @@ a piece of code, it usually means that code should be refactored or removed.
|
|||
Coverage will help to identify dead code. See
|
||||
:ref:`topics-testing-code-coverage` for details.
|
||||
|
||||
:doc:`Testing Django applications </topics/testing>` has comprehensive
|
||||
:doc:`Testing Django applications </topics/testing/index>` has comprehensive
|
||||
information about testing.
|
||||
|
||||
.. _Selenium: http://seleniumhq.org/
|
||||
|
|
|
@ -71,7 +71,7 @@ of 1.0. This includes these APIs:
|
|||
external template tags. Before adding any such tags, we'll ensure that
|
||||
Django raises an error if it tries to load tags with duplicate names.
|
||||
|
||||
- :doc:`Testing </topics/testing>`
|
||||
- :doc:`Testing </topics/testing/index>`
|
||||
|
||||
- :doc:`django-admin utility </ref/django-admin>`.
|
||||
|
||||
|
|
|
@ -1036,7 +1036,7 @@ test <app or test identifier>
|
|||
|
||||
.. django-admin:: test
|
||||
|
||||
Runs tests for all installed models. See :doc:`/topics/testing` for more
|
||||
Runs tests for all installed models. See :doc:`/topics/testing/index` for more
|
||||
information.
|
||||
|
||||
.. django-admin-option:: --failfast
|
||||
|
@ -1072,7 +1072,7 @@ For example, this command::
|
|||
|
||||
...would perform the following steps:
|
||||
|
||||
1. Create a test database, as described in :doc:`/topics/testing`.
|
||||
1. Create a test database, as described in :ref:`the-test-database`.
|
||||
2. Populate the test database with fixture data from the given fixtures.
|
||||
(For more on fixtures, see the documentation for ``loaddata`` above.)
|
||||
3. Runs the Django development server (as in ``runserver``), pointed at
|
||||
|
@ -1080,7 +1080,7 @@ For example, this command::
|
|||
|
||||
This is useful in a number of ways:
|
||||
|
||||
* When you're writing :doc:`unit tests </topics/testing>` of how your views
|
||||
* When you're writing :doc:`unit tests </topics/testing/overview>` of how your views
|
||||
act with certain fixture data, you can use ``testserver`` to interact with
|
||||
the views in a Web browser, manually.
|
||||
|
||||
|
|
|
@ -562,7 +562,7 @@ If the default value (``None``) is used with the SQLite database engine, the
|
|||
tests will use a memory resident database. For all other database engines the
|
||||
test database will use the name ``'test_' + DATABASE_NAME``.
|
||||
|
||||
See :doc:`/topics/testing`.
|
||||
See :ref:`the-test-database`.
|
||||
|
||||
.. setting:: TEST_CREATE
|
||||
|
||||
|
@ -1982,9 +1982,7 @@ TEST_RUNNER
|
|||
Default: ``'django.test.simple.DjangoTestSuiteRunner'``
|
||||
|
||||
The name of the class to use for starting the test suite. See
|
||||
:doc:`/topics/testing`.
|
||||
|
||||
.. _Testing Django Applications: ../testing/
|
||||
:ref:`other-testing-frameworks`.
|
||||
|
||||
.. setting:: THOUSAND_SEPARATOR
|
||||
|
||||
|
|
|
@ -476,7 +476,7 @@ Test signals
|
|||
.. module:: django.test.signals
|
||||
:synopsis: Signals sent during testing.
|
||||
|
||||
Signals only sent when :doc:`running tests </topics/testing>`.
|
||||
Signals only sent when :ref:`running tests <running-tests>`.
|
||||
|
||||
setting_changed
|
||||
---------------
|
||||
|
|
|
@ -220,7 +220,7 @@ supported :doc:`serialization formats </topics/serialization>`, that will be
|
|||
loaded into your database at the start of your tests. This makes testing with
|
||||
real data much easier.
|
||||
|
||||
See :doc:`the testing documentation </topics/testing>` for the full details.
|
||||
See :doc:`the testing documentation </topics/testing/index>` for the full details.
|
||||
|
||||
Improvements to the admin interface
|
||||
-----------------------------------
|
||||
|
|
|
@ -51,7 +51,7 @@ Performance improvements
|
|||
|
||||
.. currentmodule:: django.test
|
||||
|
||||
Tests written using Django's :doc:`testing framework </topics/testing>` now run
|
||||
Tests written using Django's :doc:`testing framework </topics/testing/index>` now run
|
||||
dramatically faster (as much as 10 times faster in many cases).
|
||||
|
||||
This was accomplished through the introduction of transaction-based tests: when
|
||||
|
|
|
@ -102,7 +102,7 @@ Testing improvements
|
|||
.. currentmodule:: django.test.client
|
||||
|
||||
A couple of small but very useful improvements have been made to the
|
||||
:doc:`testing framework </topics/testing>`:
|
||||
:doc:`testing framework </topics/testing/index>`:
|
||||
|
||||
* The test :class:`Client` now can automatically follow redirects with the
|
||||
``follow`` argument to :meth:`Client.get` and :meth:`Client.post`. This
|
||||
|
|
|
@ -264,14 +264,14 @@ Testing improvements
|
|||
--------------------
|
||||
|
||||
A few notable improvements have been made to the :doc:`testing framework
|
||||
</topics/testing>`.
|
||||
</topics/testing/index>`.
|
||||
|
||||
Test performance improvements
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. currentmodule:: django.test
|
||||
|
||||
Tests written using Django's :doc:`testing framework </topics/testing>` now run
|
||||
Tests written using Django's :doc:`testing framework </topics/testing/index>` now run
|
||||
dramatically faster (as much as 10 times faster in many cases).
|
||||
|
||||
This was accomplished through the introduction of transaction-based tests: when
|
||||
|
|
|
@ -13,7 +13,7 @@ Introductions to all the key parts of Django you'll need to know:
|
|||
templates
|
||||
class-based-views/index
|
||||
files
|
||||
testing
|
||||
testing/index
|
||||
auth
|
||||
cache
|
||||
conditional-view-processing
|
||||
|
|
|
@ -135,7 +135,7 @@ table once ``syncdb`` has created it. After creating a database user with these
|
|||
permissions, you'll specify the details in your project's settings file,
|
||||
see :setting:`DATABASES` for details.
|
||||
|
||||
If you're using Django's :doc:`testing framework</topics/testing>` to test
|
||||
If you're using Django's :doc:`testing framework</topics/testing/index>` to test
|
||||
database queries, Django will need permission to create a test database.
|
||||
|
||||
.. _PostgreSQL: http://www.postgresql.org/
|
||||
|
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
@ -0,0 +1,429 @@
|
|||
=======================
|
||||
Advanced testing topics
|
||||
=======================
|
||||
|
||||
The request factory
|
||||
===================
|
||||
|
||||
.. module:: django.test.client
|
||||
|
||||
.. class:: RequestFactory
|
||||
|
||||
The :class:`~django.test.client.RequestFactory` shares the same API as
|
||||
the test client. However, instead of behaving like a browser, the
|
||||
RequestFactory provides a way to generate a request instance that can
|
||||
be used as the first argument to any view. This means you can test a
|
||||
view function the same way as you would test any other function -- as
|
||||
a black box, with exactly known inputs, testing for specific outputs.
|
||||
|
||||
The API for the :class:`~django.test.client.RequestFactory` is a slightly
|
||||
restricted subset of the test client API:
|
||||
|
||||
* It only has access to the HTTP methods :meth:`~Client.get()`,
|
||||
:meth:`~Client.post()`, :meth:`~Client.put()`,
|
||||
:meth:`~Client.delete()`, :meth:`~Client.head()` and
|
||||
:meth:`~Client.options()`.
|
||||
|
||||
* These methods accept all the same arguments *except* for
|
||||
``follows``. Since this is just a factory for producing
|
||||
requests, it's up to you to handle the response.
|
||||
|
||||
* It does not support middleware. Session and authentication
|
||||
attributes must be supplied by the test itself if required
|
||||
for the view to function properly.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
The following is a simple unit test using the request factory::
|
||||
|
||||
from django.utils import unittest
|
||||
from django.test.client import RequestFactory
|
||||
|
||||
class SimpleTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
# Every test needs access to the request factory.
|
||||
self.factory = RequestFactory()
|
||||
|
||||
def test_details(self):
|
||||
# Create an instance of a GET request.
|
||||
request = self.factory.get('/customer/details')
|
||||
|
||||
# Test my_view() as if it were deployed at /customer/details
|
||||
response = my_view(request)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
.. _topics-testing-advanced-multidb:
|
||||
|
||||
Tests and multiple databases
|
||||
============================
|
||||
|
||||
.. _topics-testing-masterslave:
|
||||
|
||||
Testing master/slave configurations
|
||||
-----------------------------------
|
||||
|
||||
If you're testing a multiple database configuration with master/slave
|
||||
replication, this strategy of creating test databases poses a problem.
|
||||
When the test databases are created, there won't be any replication,
|
||||
and as a result, data created on the master won't be seen on the
|
||||
slave.
|
||||
|
||||
To compensate for this, Django allows you to define that a database is
|
||||
a *test mirror*. Consider the following (simplified) example database
|
||||
configuration::
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.mysql',
|
||||
'NAME': 'myproject',
|
||||
'HOST': 'dbmaster',
|
||||
# ... plus some other settings
|
||||
},
|
||||
'slave': {
|
||||
'ENGINE': 'django.db.backends.mysql',
|
||||
'NAME': 'myproject',
|
||||
'HOST': 'dbslave',
|
||||
'TEST_MIRROR': 'default'
|
||||
# ... plus some other settings
|
||||
}
|
||||
}
|
||||
|
||||
In this setup, we have two database servers: ``dbmaster``, described
|
||||
by the database alias ``default``, and ``dbslave`` described by the
|
||||
alias ``slave``. As you might expect, ``dbslave`` has been configured
|
||||
by the database administrator as a read slave of ``dbmaster``, so in
|
||||
normal activity, any write to ``default`` will appear on ``slave``.
|
||||
|
||||
If Django created two independent test databases, this would break any
|
||||
tests that expected replication to occur. However, the ``slave``
|
||||
database has been configured as a test mirror (using the
|
||||
:setting:`TEST_MIRROR` setting), indicating that under testing,
|
||||
``slave`` should be treated as a mirror of ``default``.
|
||||
|
||||
When the test environment is configured, a test version of ``slave``
|
||||
will *not* be created. Instead the connection to ``slave``
|
||||
will be redirected to point at ``default``. As a result, writes to
|
||||
``default`` will appear on ``slave`` -- but because they are actually
|
||||
the same database, not because there is data replication between the
|
||||
two databases.
|
||||
|
||||
.. _topics-testing-creation-dependencies:
|
||||
|
||||
Controlling creation order for test databases
|
||||
---------------------------------------------
|
||||
|
||||
By default, Django will always create the ``default`` database first.
|
||||
However, no guarantees are made on the creation order of any other
|
||||
databases in your test setup.
|
||||
|
||||
If your database configuration requires a specific creation order, you
|
||||
can specify the dependencies that exist using the
|
||||
:setting:`TEST_DEPENDENCIES` setting. Consider the following
|
||||
(simplified) example database configuration::
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
# ... db settings
|
||||
'TEST_DEPENDENCIES': ['diamonds']
|
||||
},
|
||||
'diamonds': {
|
||||
# ... db settings
|
||||
},
|
||||
'clubs': {
|
||||
# ... db settings
|
||||
'TEST_DEPENDENCIES': ['diamonds']
|
||||
},
|
||||
'spades': {
|
||||
# ... db settings
|
||||
'TEST_DEPENDENCIES': ['diamonds','hearts']
|
||||
},
|
||||
'hearts': {
|
||||
# ... db settings
|
||||
'TEST_DEPENDENCIES': ['diamonds','clubs']
|
||||
}
|
||||
}
|
||||
|
||||
Under this configuration, the ``diamonds`` database will be created first,
|
||||
as it is the only database alias without dependencies. The ``default`` and
|
||||
``clubs`` alias will be created next (although the order of creation of this
|
||||
pair is not guaranteed); then ``hearts``; and finally ``spades``.
|
||||
|
||||
If there are any circular dependencies in the
|
||||
:setting:`TEST_DEPENDENCIES` definition, an ``ImproperlyConfigured``
|
||||
exception will be raised.
|
||||
|
||||
Running tests outside the test runner
|
||||
=====================================
|
||||
|
||||
If you want to run tests outside of ``./manage.py test`` -- for example,
|
||||
from a shell prompt -- you will need to set up the test
|
||||
environment first. Django provides a convenience method to do this::
|
||||
|
||||
>>> from django.test.utils import setup_test_environment
|
||||
>>> setup_test_environment()
|
||||
|
||||
This convenience method sets up the test database, and puts other
|
||||
Django features into modes that allow for repeatable testing.
|
||||
|
||||
The call to :meth:`~django.test.utils.setup_test_environment` is made
|
||||
automatically as part of the setup of ``./manage.py test``. You only
|
||||
need to manually invoke this method if you're not using running your
|
||||
tests via Django's test runner.
|
||||
|
||||
.. _other-testing-frameworks:
|
||||
|
||||
Using different testing frameworks
|
||||
==================================
|
||||
|
||||
Clearly, :mod:`doctest` and :mod:`unittest` are not the only Python testing
|
||||
frameworks. While Django doesn't provide explicit support for alternative
|
||||
frameworks, it does provide a way to invoke tests constructed for an
|
||||
alternative framework as if they were normal Django tests.
|
||||
|
||||
When you run ``./manage.py test``, Django looks at the :setting:`TEST_RUNNER`
|
||||
setting to determine what to do. By default, :setting:`TEST_RUNNER` points to
|
||||
``'django.test.simple.DjangoTestSuiteRunner'``. This class defines the default Django
|
||||
testing behavior. This behavior involves:
|
||||
|
||||
#. Performing global pre-test setup.
|
||||
|
||||
#. Looking for unit tests and doctests in the ``models.py`` and
|
||||
``tests.py`` files in each installed application.
|
||||
|
||||
#. Creating the test databases.
|
||||
|
||||
#. Running ``syncdb`` to install models and initial data into the test
|
||||
databases.
|
||||
|
||||
#. Running the unit tests and doctests that are found.
|
||||
|
||||
#. Destroying the test databases.
|
||||
|
||||
#. Performing global post-test teardown.
|
||||
|
||||
If you define your own test runner class and point :setting:`TEST_RUNNER` at
|
||||
that class, 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, or to modify the Django test execution
|
||||
process to satisfy whatever testing requirements you may have.
|
||||
|
||||
.. _topics-testing-test_runner:
|
||||
|
||||
Defining a test runner
|
||||
----------------------
|
||||
|
||||
.. currentmodule:: django.test.simple
|
||||
|
||||
A test runner is a class defining a ``run_tests()`` method. Django ships
|
||||
with a ``DjangoTestSuiteRunner`` class that defines the default Django
|
||||
testing behavior. This class defines the ``run_tests()`` entry point,
|
||||
plus a selection of other methods that are used to by ``run_tests()`` to
|
||||
set up, execute and tear down the test suite.
|
||||
|
||||
.. class:: DjangoTestSuiteRunner(verbosity=1, interactive=True, failfast=True, **kwargs)
|
||||
|
||||
``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.
|
||||
|
||||
If ``interactive`` is ``True``, the test suite has permission to ask the
|
||||
user for instructions when the test suite is executed. An example of this
|
||||
behavior would be asking for permission to delete an existing test
|
||||
database. If ``interactive`` is ``False``, the test suite must be able to
|
||||
run without any manual intervention.
|
||||
|
||||
If ``failfast`` is ``True``, the test suite will stop running after the
|
||||
first test failure is detected.
|
||||
|
||||
Django will, from time to time, extend the capabilities of
|
||||
the test runner by adding new arguments. The ``**kwargs`` declaration
|
||||
allows for this expansion. If you subclass ``DjangoTestSuiteRunner`` or
|
||||
write your own test runner, ensure accept and handle the ``**kwargs``
|
||||
parameter.
|
||||
|
||||
.. versionadded:: 1.4
|
||||
|
||||
Your test runner may also define additional command-line options.
|
||||
If you add an ``option_list`` attribute to a subclassed test runner,
|
||||
those options will be added to the list of command-line options that
|
||||
the :djadmin:`test` command can use.
|
||||
|
||||
Attributes
|
||||
~~~~~~~~~~
|
||||
|
||||
.. attribute:: DjangoTestSuiteRunner.option_list
|
||||
|
||||
.. versionadded:: 1.4
|
||||
|
||||
This is the tuple of ``optparse`` options which will be fed into the
|
||||
management command's ``OptionParser`` for parsing arguments. See the
|
||||
documentation for Python's ``optparse`` module for more details.
|
||||
|
||||
Methods
|
||||
~~~~~~~
|
||||
|
||||
.. method:: DjangoTestSuiteRunner.run_tests(test_labels, extra_tests=None, **kwargs)
|
||||
|
||||
Run the test suite.
|
||||
|
||||
``test_labels`` is a list of strings describing the tests to be run. A test
|
||||
label can take one of three forms:
|
||||
|
||||
* ``app.TestCase.test_method`` -- Run a single test method in a test
|
||||
case.
|
||||
* ``app.TestCase`` -- Run all the test methods in a test case.
|
||||
* ``app`` -- Search for and run all tests in the named application.
|
||||
|
||||
If ``test_labels`` has a value of ``None``, the test runner should run
|
||||
search for tests in all the applications in :setting:`INSTALLED_APPS`.
|
||||
|
||||
``extra_tests`` is a list of extra ``TestCase`` instances to add to the
|
||||
suite that is executed by the test runner. These extra tests are run
|
||||
in addition to those discovered in the modules listed in ``test_labels``.
|
||||
|
||||
This method should return the number of tests that failed.
|
||||
|
||||
.. method:: DjangoTestSuiteRunner.setup_test_environment(**kwargs)
|
||||
|
||||
Sets up the test environment ready for testing.
|
||||
|
||||
.. method:: DjangoTestSuiteRunner.build_suite(test_labels, extra_tests=None, **kwargs)
|
||||
|
||||
Constructs a test suite that matches the test labels provided.
|
||||
|
||||
``test_labels`` is a list of strings describing the tests to be run. A test
|
||||
label can take one of three forms:
|
||||
|
||||
* ``app.TestCase.test_method`` -- Run a single test method in a test
|
||||
case.
|
||||
* ``app.TestCase`` -- Run all the test methods in a test case.
|
||||
* ``app`` -- Search for and run all tests in the named application.
|
||||
|
||||
If ``test_labels`` has a value of ``None``, the test runner should run
|
||||
search for tests in all the applications in :setting:`INSTALLED_APPS`.
|
||||
|
||||
``extra_tests`` is a list of extra ``TestCase`` instances to add to the
|
||||
suite that is executed by the test runner. These extra tests are run
|
||||
in addition to those discovered in the modules listed in ``test_labels``.
|
||||
|
||||
Returns a ``TestSuite`` instance ready to be run.
|
||||
|
||||
.. method:: DjangoTestSuiteRunner.setup_databases(**kwargs)
|
||||
|
||||
Creates the test databases.
|
||||
|
||||
Returns a data structure that provides enough detail to undo the changes
|
||||
that have been made. This data will be provided to the ``teardown_databases()``
|
||||
function at the conclusion of testing.
|
||||
|
||||
.. method:: DjangoTestSuiteRunner.run_suite(suite, **kwargs)
|
||||
|
||||
Runs the test suite.
|
||||
|
||||
Returns the result produced by the running the test suite.
|
||||
|
||||
.. method:: DjangoTestSuiteRunner.teardown_databases(old_config, **kwargs)
|
||||
|
||||
Destroys the test databases, restoring pre-test conditions.
|
||||
|
||||
``old_config`` is a data structure defining the changes in the
|
||||
database configuration that need to be reversed. It is the return
|
||||
value of the ``setup_databases()`` method.
|
||||
|
||||
.. method:: DjangoTestSuiteRunner.teardown_test_environment(**kwargs)
|
||||
|
||||
Restores the pre-test environment.
|
||||
|
||||
.. method:: DjangoTestSuiteRunner.suite_result(suite, result, **kwargs)
|
||||
|
||||
Computes and returns a return code based on a test suite, and the result
|
||||
from that test suite.
|
||||
|
||||
|
||||
Testing utilities
|
||||
-----------------
|
||||
|
||||
.. 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.
|
||||
|
||||
.. 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 email outbox.
|
||||
|
||||
.. function:: teardown_test_environment()
|
||||
|
||||
Performs any global post-test teardown, such as removing the black
|
||||
magic hooks into the template system and restoring normal email
|
||||
services.
|
||||
|
||||
.. currentmodule:: django.db.connection.creation
|
||||
|
||||
The creation module of the database backend (``connection.creation``)
|
||||
also provides some utilities that can be useful during testing.
|
||||
|
||||
.. function:: create_test_db([verbosity=1, autoclobber=False])
|
||||
|
||||
Creates a new test database and runs ``syncdb`` against it.
|
||||
|
||||
``verbosity`` has the same behavior as in ``run_tests()``.
|
||||
|
||||
``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.
|
||||
|
||||
Returns the name of the test database that it created.
|
||||
|
||||
``create_test_db()`` has the side effect of modifying the value of
|
||||
:setting:`NAME` in :setting:`DATABASES` to match the name of the test
|
||||
database.
|
||||
|
||||
.. function:: destroy_test_db(old_database_name, [verbosity=1])
|
||||
|
||||
Destroys the database whose name is the value of :setting:`NAME` in
|
||||
:setting:`DATABASES`, and sets :setting:`NAME` to the value of
|
||||
``old_database_name``.
|
||||
|
||||
The ``verbosity`` argument has the same behavior as for
|
||||
:class:`~django.test.simple.DjangoTestSuiteRunner`.
|
||||
|
||||
.. _topics-testing-code-coverage:
|
||||
|
||||
Integration with coverage.py
|
||||
============================
|
||||
|
||||
Code coverage describes how much source code has been tested. It shows which
|
||||
parts of your code are being exercised by tests and which are not. It's an
|
||||
important part of testing applications, so it's strongly recommended to check
|
||||
the coverage of your tests.
|
||||
|
||||
Django can be easily integrated with `coverage.py`_, a tool for measuring code
|
||||
coverage of Python programs. First, `install coverage.py`_. Next, run the
|
||||
following from your project folder containing ``manage.py``::
|
||||
|
||||
coverage run --source='.' manage.py test myapp
|
||||
|
||||
This runs your tests and collects coverage data of the executed files in your
|
||||
project. You can see a report of this data by typing following command::
|
||||
|
||||
coverage report
|
||||
|
||||
Note that some Django code was executed while running tests, but it is not
|
||||
listed here because of the ``source`` flag passed to the previous command.
|
||||
|
||||
For more options like annotated HTML listings detailing missed lines, see the
|
||||
`coverage.py`_ docs.
|
||||
|
||||
.. _coverage.py: http://nedbatchelder.com/code/coverage/
|
||||
.. _install coverage.py: http://pypi.python.org/pypi/coverage
|
|
@ -0,0 +1,81 @@
|
|||
===================
|
||||
Django and doctests
|
||||
===================
|
||||
|
||||
Doctests use Python's standard :mod:`doctest` module, which searches your
|
||||
docstrings for statements that resemble a session of the Python interactive
|
||||
interpreter. A full explanation of how :mod:`doctest` works is out of the scope
|
||||
of this document; read Python's official documentation for the details.
|
||||
|
||||
.. admonition:: What's a **docstring**?
|
||||
|
||||
A good explanation of docstrings (and some guidelines for using them
|
||||
effectively) can be found in :pep:`257`:
|
||||
|
||||
A docstring is a string literal that occurs as the first statement in
|
||||
a module, function, class, or method definition. Such a docstring
|
||||
becomes the ``__doc__`` special attribute of that object.
|
||||
|
||||
For example, this function has a docstring that describes what it does::
|
||||
|
||||
def add_two(num):
|
||||
"Return the result of adding two to the provided number."
|
||||
return num + 2
|
||||
|
||||
Because tests often make great documentation, putting tests directly in
|
||||
your docstrings is an effective way to document *and* test your code.
|
||||
|
||||
As with unit tests, for a given Django application, the test runner looks for
|
||||
doctests in two places:
|
||||
|
||||
* The ``models.py`` file. You can define module-level doctests and/or a
|
||||
doctest for individual models. It's common practice to put
|
||||
application-level doctests in the module docstring and model-level
|
||||
doctests in the model docstrings.
|
||||
|
||||
* A file called ``tests.py`` in the application directory -- i.e., the
|
||||
directory that holds ``models.py``. This file is a hook for any and all
|
||||
doctests you want to write that aren't necessarily related to models.
|
||||
|
||||
This example doctest is equivalent to the example given in the unittest section
|
||||
above::
|
||||
|
||||
# models.py
|
||||
|
||||
from django.db import models
|
||||
|
||||
class Animal(models.Model):
|
||||
"""
|
||||
An animal that knows how to make noise
|
||||
|
||||
# Create some animals
|
||||
>>> lion = Animal.objects.create(name="lion", sound="roar")
|
||||
>>> cat = Animal.objects.create(name="cat", sound="meow")
|
||||
|
||||
# Make 'em speak
|
||||
>>> lion.speak()
|
||||
'The lion says "roar"'
|
||||
>>> cat.speak()
|
||||
'The cat says "meow"'
|
||||
"""
|
||||
name = models.CharField(max_length=20)
|
||||
sound = models.CharField(max_length=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.
|
||||
|
||||
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. However, the database is not refreshed between doctests,
|
||||
so if your doctest requires a certain state you should consider flushing the
|
||||
database or loading a fixture. (See the section on :ref:`fixtures
|
||||
<topics-testing-fixtures>` 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 :mod:`doctest`, see the Python documentation.
|
|
@ -0,0 +1,111 @@
|
|||
=================
|
||||
Testing in Django
|
||||
=================
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
|
||||
overview
|
||||
doctests
|
||||
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:
|
||||
|
||||
* When you're writing new code, you can use tests to validate your code
|
||||
works as expected.
|
||||
|
||||
* When you're refactoring or modifying old code, you can use tests to
|
||||
ensure your changes haven't affected your application's behavior
|
||||
unexpectedly.
|
||||
|
||||
Testing a Web application is a complex task, because a Web application is made
|
||||
of several layers of logic -- from HTTP-level request handling, to form
|
||||
validation and processing, to template rendering. With Django's test-execution
|
||||
framework and assorted utilities, you can simulate requests, insert test data,
|
||||
inspect your application's output and generally verify your code is doing what
|
||||
it should be doing.
|
||||
|
||||
The best part is, it's really easy.
|
||||
|
||||
Unit tests v. doctests
|
||||
======================
|
||||
|
||||
There are two primary ways to write tests with Django, corresponding to the
|
||||
two test frameworks that ship in the Python standard library. The two
|
||||
frameworks are:
|
||||
|
||||
* **Unit tests** -- tests that are expressed as methods on a Python class
|
||||
that subclasses :class:`unittest.TestCase` or Django's customized
|
||||
:class:`TestCase`. For example::
|
||||
|
||||
import unittest
|
||||
|
||||
class MyFuncTestCase(unittest.TestCase):
|
||||
def testBasic(self):
|
||||
a = ['larry', 'curly', 'moe']
|
||||
self.assertEqual(my_func(a, 0), 'larry')
|
||||
self.assertEqual(my_func(a, 1), 'curly')
|
||||
|
||||
* **Doctests** -- tests that are embedded in your functions' docstrings and
|
||||
are written in a way that emulates a session of the Python interactive
|
||||
interpreter. For example::
|
||||
|
||||
def my_func(a_list, idx):
|
||||
"""
|
||||
>>> a = ['larry', 'curly', 'moe']
|
||||
>>> my_func(a, 0)
|
||||
'larry'
|
||||
>>> my_func(a, 1)
|
||||
'curly'
|
||||
"""
|
||||
return a_list[idx]
|
||||
|
||||
Which should I use?
|
||||
-------------------
|
||||
|
||||
Because Django supports both of the standard Python test frameworks, it's up to
|
||||
you and your tastes to decide which one to use. You can even decide to use
|
||||
*both*.
|
||||
|
||||
For developers new to testing, however, this choice can seem confusing. Here,
|
||||
then, are a few key differences to help you decide which approach is right for
|
||||
you:
|
||||
|
||||
* If you've been using Python for a while, :mod:`doctest` will probably feel
|
||||
more "pythonic". It's designed to make writing tests as easy as possible,
|
||||
so it requires no overhead of writing classes or methods. You simply put
|
||||
tests in docstrings. This has the added advantage of serving as
|
||||
documentation (and correct documentation, at that!). However, while
|
||||
doctests are good for some simple example code, they are not very good if
|
||||
you want to produce either high quality, comprehensive tests or high
|
||||
quality documentation. Test failures are often difficult to debug
|
||||
as it can be unclear exactly why the test failed. Thus, doctests should
|
||||
generally be avoided and used primarily for documentation examples only.
|
||||
|
||||
* The :mod:`unittest` framework will probably feel very familiar to
|
||||
developers coming from Java. :mod:`unittest` is inspired by Java's JUnit,
|
||||
so you'll feel at home with this method if you've used JUnit or any test
|
||||
framework inspired by JUnit.
|
||||
|
||||
* If you need to write a bunch of tests that share similar code, then
|
||||
you'll appreciate the :mod:`unittest` framework's organization around
|
||||
classes and methods. This makes it easy to abstract common tasks into
|
||||
common methods. The framework also supports explicit setup and/or cleanup
|
||||
routines, which give you a high level of control over the environment
|
||||
in which your test cases are run.
|
||||
|
||||
* If you're writing tests for Django itself, you should use :mod:`unittest`.
|
||||
|
||||
Where to go from here
|
||||
=====================
|
||||
|
||||
As unit tests are preferred in Django, we treat them in detail in the
|
||||
:doc:`overview` document.
|
||||
|
||||
:doc:`doctests` describes Django-specific features when using doctests.
|
||||
|
||||
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`.
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue