Fixed #8138 -- Changed django.test.TestCase to rollback tests (when the database supports it) instead of flushing and reloading the database. This can substantially reduce the time it takes to run large test suites.

This change may be slightly backwards incompatible, if existing tests need to test transactional behavior, or if they rely on invalid assumptions or a specific test case ordering.  For the first case, django.test.TransactionTestCase should be used.  TransactionTestCase is also a quick fix to get around test case errors revealed by the new rollback approach, but a better long-term fix is to correct the test case.  See the testing doc for full details.

Many thanks to:
* Marc Remolt for the initial proposal and implementation.
* Luke Plant for initial testing and improving the implementation.
* Ramiro Morales for feedback and help with tracking down a mysterious PostgreSQL issue.
* Eric Holscher for feedback regarding the effect of the change on the Ellington testsuite.
* Russell Keith-Magee for guidance and feedback from beginning to end.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@9756 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Karen Tracey 2009-01-16 02:30:22 +00:00
parent f9f9d703cf
commit 344f16e220
11 changed files with 251 additions and 51 deletions

View file

@ -785,6 +785,52 @@ just change the base class of your test from ``unittest.TestCase`` to
will continue to be available, but it will be augmented with some useful
additions.
.. versionadded:: 1.1
.. class:: TransactionTestCase()
Django ``TestCase`` classes make use of database transaction facilities, if
available, 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 ``TranscationTestCase`` resets
the database before the test runs by truncating all tables and reloading
initial data. 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 and reload initial
data at the beginning of a test. Instead, it encloses the test code in a
database transaction that is rolled back at the end of the test. It also
prevents the code under test from issuing any commit or rollback operations
on the database, to ensure that the rollback at the end of the test restores
the database to its initial state. In order to guarantee that all ``TestCase``
code starts with a clean database, the Django test runner runs all ``TestCase``
tests first, before any other tests (e.g. doctests) that may alter the
database without restoring it to its original 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.
.. note::
The ``TestCase`` use of rollback to un-do the effects of the test code
may reveal previously-undetected errors in test code. For example,
test code that assumes primary keys values will be assigned starting at
one may find that assumption no longer holds true when rollbacks instead
of table truncation are being used to reset the database. Similarly,
the reordering of tests so that all ``TestCase`` classes run first may
reveal unexpected dependencies on test case ordering. In such cases a
quick fix is to switch the ``TestCase`` to a ``TransactionTestCase``.
A better long-term fix, that allows the test to take advantage of the
speed benefit of ``TestCase``, is to fix the underlying test problem.
Default test client
~~~~~~~~~~~~~~~~~~~