mirror of
https://github.com/django/django.git
synced 2025-10-17 22:07:29 +00:00
Fixed #20579 -- Improved TransactionTestCase.available_apps.
Also moved its documentation to the 'advanced' section. It doesn't belong to the 'overview'. Same for TransactionTestCase.reset_sequences. When available_apps is set, after a TransactionTestCase, the database is now totally empty. post_syncdb is fired at the beginning of the next TransactionTestCase. Refs #20483.
This commit is contained in:
parent
0938970491
commit
55cbd65985
4 changed files with 130 additions and 87 deletions
|
@ -155,6 +155,80 @@ If there are any circular dependencies in the
|
|||
:setting:`TEST_DEPENDENCIES` definition, an ``ImproperlyConfigured``
|
||||
exception will be raised.
|
||||
|
||||
Advanced features of ``TransactionTestCase``
|
||||
============================================
|
||||
|
||||
.. currentmodule:: django.test
|
||||
|
||||
.. attribute:: TransactionTestCase.available_apps
|
||||
|
||||
.. versionadded:: 1.6
|
||||
|
||||
.. warning::
|
||||
|
||||
This attribute is a private API. It may be changed or removed without
|
||||
a deprecation period in the future, for instance to accomodate changes
|
||||
in application loading.
|
||||
|
||||
It's used to optimize Django's own test suite, which contains hundreds
|
||||
of models but no relations between models in different applications.
|
||||
|
||||
By default, ``available_apps`` is set to ``None``. After each test, Django
|
||||
calls :djadmin:`flush` to reset the database state. This empties all tables
|
||||
and emits the :data:`~django.db.models.signals.post_syncdb` signal, which
|
||||
re-creates one content type and three permissions for each model. This
|
||||
operation gets expensive proportionally to the number of models.
|
||||
|
||||
Setting ``available_apps`` to a list of applications instructs Django to
|
||||
behave as if only the models from these applications were available. The
|
||||
behavior of ``TransactionTestCase`` changes as follows:
|
||||
|
||||
- :data:`~django.db.models.signals.post_syncdb` is fired before each
|
||||
test to create the content types and permissions for each model in
|
||||
available apps, in case they're missing.
|
||||
- After each test, Django empties only tables corresponding to models in
|
||||
available apps. However, at the database level, truncation may cascade to
|
||||
related models in unavailable apps. Furthermore
|
||||
:data:`~django.db.models.signals.post_syncdb` isn't fired; it will be
|
||||
fired by the next ``TransactionTestCase``, after the correct set of
|
||||
applications is selected.
|
||||
|
||||
Since the database isn't fully flushed, if a test creates instances of
|
||||
models not included in ``available_apps``, they will leak and they may
|
||||
cause unrelated tests to fail. Be careful with tests that use sessions;
|
||||
the default session engine stores them in the database.
|
||||
|
||||
Since :data:`~django.db.models.signals.post_syncdb` isn't emitted after
|
||||
flushing the database, its state after a ``TransactionTestCase`` isn't the
|
||||
same as after a ``TestCase``: it's missing the rows created by listeners
|
||||
to :data:`~django.db.models.signals.post_syncdb`. Considering the
|
||||
:ref:`order in which tests are executed <order-of-tests>`, this isn't an
|
||||
issue, provided either all ``TransactionTestCase`` in a given test suite
|
||||
declare ``available_apps``, or none of them.
|
||||
|
||||
``available_apps`` is mandatory in Django's own test suite.
|
||||
|
||||
.. attribute:: TransactionTestCase.reset_sequences
|
||||
|
||||
.. versionadded:: 1.5
|
||||
|
||||
Setting ``reset_sequences = True`` on a ``TransactionTestCase`` will make
|
||||
sure sequences are always reset before the test run::
|
||||
|
||||
class TestsThatDependsOnPrimaryKeySequences(TransactionTestCase):
|
||||
reset_sequences = True
|
||||
|
||||
def test_animal_pk(self):
|
||||
lion = Animal.objects.create(name="lion", sound="roar")
|
||||
# lion.pk is guaranteed to always be 1
|
||||
self.assertEqual(lion.pk, 1)
|
||||
|
||||
Unless you are explicitly testing primary keys sequence numbers, it is
|
||||
recommended that you do not hard code primary key values in tests.
|
||||
|
||||
Using ``reset_sequences = True`` will slow down the test, since the primary
|
||||
key reset is an relatively expensive database operation.
|
||||
|
||||
Running tests outside the test runner
|
||||
=====================================
|
||||
|
||||
|
|
|
@ -213,6 +213,8 @@ advanced settings.
|
|||
|
||||
The :ref:`advanced multi-db testing topics <topics-testing-advanced-multidb>`.
|
||||
|
||||
.. _order-of-tests:
|
||||
|
||||
Order in which tests are executed
|
||||
---------------------------------
|
||||
|
||||
|
@ -908,8 +910,8 @@ TransactionTestCase
|
|||
|
||||
.. 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
|
||||
Django's ``TestCase`` class (described below) makes use of database transaction
|
||||
facilities 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
|
||||
|
@ -927,9 +929,9 @@ to test the effects of commit and rollback:
|
|||
Instead, it encloses the test code in a database transaction that is rolled
|
||||
back at the end of the test. Both explicit commits like
|
||||
``transaction.commit()`` and implicit ones that may be caused by
|
||||
``Model.save()`` are replaced with a ``nop`` operation. This guarantees that
|
||||
the rollback at the end of the test restores the database to its initial
|
||||
state.
|
||||
``transaction.atomic()`` are replaced with a ``nop`` operation. This
|
||||
guarantees that the rollback at the end of the test restores the database to
|
||||
its initial 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
|
||||
|
@ -940,22 +942,21 @@ to test the effects of commit and rollback:
|
|||
While ``commit`` and ``rollback`` operations still *appear* to work when
|
||||
used in ``TestCase``, no actual commit or rollback will be performed by the
|
||||
database. This can cause your tests to pass or fail unexpectedly. Always
|
||||
use ``TransactionalTestCase`` when testing transactional behavior.
|
||||
use ``TransactionTestCase`` when testing transactional behavior.
|
||||
|
||||
.. note::
|
||||
.. versionchanged:: 1.5
|
||||
|
||||
.. versionchanged:: 1.5
|
||||
|
||||
Prior to 1.5, ``TransactionTestCase`` flushed the database tables *before*
|
||||
each test. In Django 1.5, this is instead done *after* the test has been run.
|
||||
Prior to 1.5, :class:`~django.test.TransactionTestCase` flushed the
|
||||
database tables *before* each test. In Django 1.5, this is instead done
|
||||
*after* the test has been run.
|
||||
|
||||
When the flush took place before the test, it was guaranteed that primary
|
||||
key values started at one in :class:`~django.test.TransactionTestCase`
|
||||
tests.
|
||||
|
||||
Tests should not depend on this behavior, but for legacy tests that do, the
|
||||
:attr:`~TransactionTestCase.reset_sequences` attribute can be used until
|
||||
the test has been properly updated.
|
||||
Tests should not depend on this behavior, but for legacy tests that do,
|
||||
the :attr:`~TransactionTestCase.reset_sequences` attribute can be used
|
||||
until the test has been properly updated.
|
||||
|
||||
.. versionchanged:: 1.5
|
||||
|
||||
|
@ -964,55 +965,6 @@ to test the effects of commit and rollback:
|
|||
|
||||
``TransactionTestCase`` inherits from :class:`~django.test.SimpleTestCase`.
|
||||
|
||||
.. attribute:: TransactionTestCase.reset_sequences
|
||||
|
||||
.. versionadded:: 1.5
|
||||
|
||||
Setting ``reset_sequences = True`` on a ``TransactionTestCase`` will make
|
||||
sure sequences are always reset before the test run::
|
||||
|
||||
class TestsThatDependsOnPrimaryKeySequences(TransactionTestCase):
|
||||
reset_sequences = True
|
||||
|
||||
def test_animal_pk(self):
|
||||
lion = Animal.objects.create(name="lion", sound="roar")
|
||||
# lion.pk is guaranteed to always be 1
|
||||
self.assertEqual(lion.pk, 1)
|
||||
|
||||
Unless you are explicitly testing primary keys sequence numbers, it is
|
||||
recommended that you do not hard code primary key values in tests.
|
||||
|
||||
Using ``reset_sequences = True`` will slow down the test, since the primary
|
||||
key reset is an relatively expensive database operation.
|
||||
|
||||
.. attribute:: TransactionTestCase.available_apps
|
||||
|
||||
.. warning::
|
||||
|
||||
This attribute is a private API. It may be changed or removed without
|
||||
a deprecation period in the future, for instance to accomodate changes
|
||||
in application loading.
|
||||
|
||||
It's used to optimize Django's own test suite, which contains hundreds
|
||||
of models but no relations between models in different applications.
|
||||
|
||||
.. versionadded:: 1.6
|
||||
|
||||
By default, ``available_apps`` is set to ``None`` and has no effect.
|
||||
Setting it to a list of applications tells Django to behave as if only the
|
||||
models from these applications were available:
|
||||
|
||||
- Before each test, Django creates content types and permissions only for
|
||||
these models.
|
||||
- After each test, Django flushes only the corresponding tables. However,
|
||||
at the database level, truncation may cascade to other related models,
|
||||
even if they aren't in ``available_apps``.
|
||||
|
||||
Since the database isn't fully flushed, if a test creates instances of
|
||||
models not included in ``available_apps``, they will leak and they may
|
||||
cause unrelated tests to fail. Be careful with tests that use sessions;
|
||||
the default session engine stores them in the database.
|
||||
|
||||
TestCase
|
||||
~~~~~~~~
|
||||
|
||||
|
@ -1495,7 +1447,7 @@ Emptying the test outbox
|
|||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you use any of Django's custom ``TestCase`` classes, the test runner will
|
||||
clear thecontents of the test email outbox at the start of each test case.
|
||||
clear the contents of the test email outbox at the start of each test case.
|
||||
|
||||
For more detail on email services during tests, see `Email services`_ below.
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue