Refs #2333 - Added more documentation for testing framework, and clarified some code as a result of trying to describe it.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@3689 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
d9883e1dec
commit
fc2d5f461f
|
@ -61,7 +61,8 @@ def run_tests(module_list, verbosity=1, extra_tests=[]):
|
||||||
for test in extra_tests:
|
for test in extra_tests:
|
||||||
suite.addTest(test)
|
suite.addTest(test)
|
||||||
|
|
||||||
old_name = create_test_db(verbosity)
|
old_name = settings.DATABASE_NAME
|
||||||
|
create_test_db(verbosity)
|
||||||
management.syncdb(verbosity, interactive=False)
|
management.syncdb(verbosity, interactive=False)
|
||||||
unittest.TextTestRunner(verbosity=verbosity).run(suite)
|
unittest.TextTestRunner(verbosity=verbosity).run(suite)
|
||||||
destroy_test_db(old_name, verbosity)
|
destroy_test_db(old_name, verbosity)
|
||||||
|
|
|
@ -50,15 +50,12 @@ def create_test_db(verbosity=1, autoclobber=False):
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
connection.close()
|
connection.close()
|
||||||
old_database_name = settings.DATABASE_NAME
|
|
||||||
settings.DATABASE_NAME = TEST_DATABASE_NAME
|
settings.DATABASE_NAME = TEST_DATABASE_NAME
|
||||||
|
|
||||||
# Get a cursor (even though we don't need one yet). This has
|
# Get a cursor (even though we don't need one yet). This has
|
||||||
# the side effect of initializing the test database.
|
# the side effect of initializing the test database.
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
|
|
||||||
return old_database_name
|
|
||||||
|
|
||||||
def destroy_test_db(old_database_name, verbosity=1):
|
def destroy_test_db(old_database_name, verbosity=1):
|
||||||
# Unless we're using SQLite, remove the test database to clean up after
|
# Unless we're using SQLite, remove the test database to clean up after
|
||||||
# ourselves. Connect to the previous database (not the test database)
|
# ourselves. Connect to the previous database (not the test database)
|
||||||
|
|
|
@ -345,6 +345,17 @@ setting the Python path for you.
|
||||||
Displays a help message that includes a terse list of all available actions and
|
Displays a help message that includes a terse list of all available actions and
|
||||||
options.
|
options.
|
||||||
|
|
||||||
|
--noinput
|
||||||
|
---------
|
||||||
|
|
||||||
|
Inform django-admin that the user should NOT be prompted for any input. Useful if
|
||||||
|
the django-admin script will be executed as an unattended, automated script.
|
||||||
|
|
||||||
|
--noreload
|
||||||
|
----------
|
||||||
|
|
||||||
|
Disable the use of the auto-reloader when running the development server.
|
||||||
|
|
||||||
--version
|
--version
|
||||||
---------
|
---------
|
||||||
|
|
||||||
|
@ -355,6 +366,17 @@ Example output::
|
||||||
0.9.1
|
0.9.1
|
||||||
0.9.1 (SVN)
|
0.9.1 (SVN)
|
||||||
|
|
||||||
|
--verbosity
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Example usage::
|
||||||
|
|
||||||
|
django-admin.py syncdb --verbosity=2
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
Extra niceties
|
Extra niceties
|
||||||
==============
|
==============
|
||||||
|
|
||||||
|
|
|
@ -754,6 +754,18 @@ misspelled) variables. See `How invalid variables are handled`_.
|
||||||
|
|
||||||
.. _How invalid variables are handled: http://www.djangoproject.com/documentation/templates_python/#how-invalid-variables-are-handled
|
.. _How invalid variables are handled: http://www.djangoproject.com/documentation/templates_python/#how-invalid-variables-are-handled
|
||||||
|
|
||||||
|
TEST_RUNNER
|
||||||
|
-----------
|
||||||
|
|
||||||
|
**New in Django development version**
|
||||||
|
|
||||||
|
Default: ``'django.test.simple.run_tests'``
|
||||||
|
|
||||||
|
The name of the method to use for starting the test suite. See
|
||||||
|
`Testing Django Applications`_.
|
||||||
|
|
||||||
|
.. _Testing Django Applications: ../testing/
|
||||||
|
|
||||||
TIME_FORMAT
|
TIME_FORMAT
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
|
124
docs/testing.txt
124
docs/testing.txt
|
@ -4,9 +4,17 @@ Testing Django applications
|
||||||
|
|
||||||
**New in Django development version**.
|
**New in Django development version**.
|
||||||
|
|
||||||
.. XXX insert quick introduction to testing (and why you'd want to do it)
|
Automated testing is an extremely useful weapon in the bug-killing arsenal
|
||||||
|
of the modern developer. When initially writing code, a test suite can be
|
||||||
|
used to validate that code behaves as expected. When refactoring or
|
||||||
|
modifying code, tests serve as a guide to ensure that behavior hasn't
|
||||||
|
changed as a result of the refactor.
|
||||||
|
|
||||||
.. note::
|
Testing an web application is a complex task, as there are many
|
||||||
|
components of a web application that must be validated and tested. To
|
||||||
|
help you test your application, Django provides a test execution
|
||||||
|
framework, and range of utilities that can be used to stimulate and
|
||||||
|
inspect various facets of a web application.
|
||||||
|
|
||||||
This testing framework is currently under development, and may change
|
This testing framework is currently under development, and may change
|
||||||
slightly before the next official Django release.
|
slightly before the next official Django release.
|
||||||
|
@ -23,7 +31,10 @@ Writing doctests
|
||||||
|
|
||||||
Doctests use Python's standard doctest_ module, which searches for tests in
|
Doctests use Python's standard doctest_ module, which searches for tests in
|
||||||
your docstrings. Django's test runner looks for doctests in your ``models.py``
|
your docstrings. Django's test runner looks for doctests in your ``models.py``
|
||||||
file, and executes any that it finds.
|
file, and executes any that it finds. Django will also search for a file
|
||||||
|
called ``tests.py`` in the application directory (i.e., the directory that
|
||||||
|
holds ``models.py``). If a ``tests.py`` is found, it will also be searched
|
||||||
|
for doctests.
|
||||||
|
|
||||||
.. admonition:: What's a **docstring**?
|
.. admonition:: What's a **docstring**?
|
||||||
|
|
||||||
|
@ -80,8 +91,8 @@ Writing unittests
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
Like doctests, Django's unit tests use a standard library module: unittest_.
|
Like doctests, Django's unit tests use a standard library module: unittest_.
|
||||||
Django's test runner looks for unit test cases in a ``tests.py`` file in your
|
As with doctests, Django's test runner looks for any unit test cases defined
|
||||||
app (i.e. in the same directory as your ``models.py`` file).
|
in ``models.py``, or in a ``tests.py`` file in your application directory.
|
||||||
|
|
||||||
An equivalent unittest test case for the above example would look like::
|
An equivalent unittest test case for the above example would look like::
|
||||||
|
|
||||||
|
@ -148,6 +159,20 @@ 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
|
app). In the end, most projects will eventually end up using both; each shines
|
||||||
in different circumstances.
|
in different circumstances.
|
||||||
|
|
||||||
|
Testing utilities
|
||||||
|
=================
|
||||||
|
|
||||||
|
Test Client
|
||||||
|
-----------
|
||||||
|
|
||||||
|
A dummy browser; instruments the template generation process...
|
||||||
|
|
||||||
|
Fixtures
|
||||||
|
--------
|
||||||
|
|
||||||
|
Feature still to come...
|
||||||
|
|
||||||
|
|
||||||
Running tests
|
Running tests
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
@ -155,9 +180,22 @@ Run your tests using your project's ``manage.py`` utility::
|
||||||
|
|
||||||
$ ./manage.py test
|
$ ./manage.py test
|
||||||
|
|
||||||
You'll see a bunch of text flow by as the test database is created, models are
|
If you only want to run tests for a particular application, add the
|
||||||
initialized, and your tests are run. If everything goes well, at the end
|
application name to the command line. For example, if your
|
||||||
you'll see::
|
``INSTALLED_APPS`` contains ``myproject.polls`` and ``myproject.animals``,
|
||||||
|
but you only want to run the animals unit tests, run::
|
||||||
|
|
||||||
|
$ ./manage.py test animals
|
||||||
|
|
||||||
|
When you run your tests, you'll see a bunch of text flow by as the test
|
||||||
|
database is created and models are initialized. This test database is
|
||||||
|
created from scratch every time you run your tests. The test database
|
||||||
|
gets its name by prepending ``test_`` to the database name specified by
|
||||||
|
``settings.DATABASE_NAME``; all other database settings will the same as
|
||||||
|
they would be for the project normally.
|
||||||
|
|
||||||
|
Once the test database has been established, Django will run your tests.
|
||||||
|
If everything goes well, at the end you'll see::
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
Ran 22 tests in 0.221s
|
Ran 22 tests in 0.221s
|
||||||
|
@ -190,3 +228,73 @@ failed::
|
||||||
|
|
||||||
FAILED (failures=1)
|
FAILED (failures=1)
|
||||||
|
|
||||||
|
When the tests have all been executed, the test database is destroyed.
|
||||||
|
|
||||||
|
Using a different testing framework
|
||||||
|
===================================
|
||||||
|
|
||||||
|
Doctest and Unittest are not the only Python testing frameworks. While
|
||||||
|
Django doesn't provide explicit support these alternative frameworks,
|
||||||
|
it does provide a mechanism to allow you 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 ``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:
|
||||||
|
|
||||||
|
#. 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.
|
||||||
|
|
||||||
|
If you define your own test runner method and point ``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.
|
||||||
|
|
||||||
|
Defining a test runner
|
||||||
|
----------------------
|
||||||
|
By convention, a test runner should be called ``run_tests``; however, you
|
||||||
|
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()``
|
||||||
|
|
||||||
|
Verbosity determines the amount of debug information that will be
|
||||||
|
provided to the console; '0' is no output, '1' is normal output,
|
||||||
|
and `2` is verbose output.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
``create_test_db(verbosity=1, autoclobber=False)``:
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Creates a new test database, and run ``syncdb`` against it.
|
||||||
|
|
||||||
|
``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.
|
||||||
|
|
||||||
|
``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.
|
||||||
|
|
||||||
|
``verbosity`` has the same behaviour as in the test runner.
|
||||||
|
|
Loading…
Reference in New Issue