Refs #20392 -- Load fixtures once within TestCase
This commit is contained in:
parent
0dea81cd6d
commit
119154ca7f
|
@ -915,24 +915,46 @@ class TestCase(TransactionTestCase):
|
|||
On database backends with no transaction support, TestCase behaves as
|
||||
TransactionTestCase.
|
||||
"""
|
||||
@classmethod
|
||||
def _enter_atomics(cls):
|
||||
"""Helper method to open atomic blocks for multiple databases"""
|
||||
atomics = {}
|
||||
for db_name in cls._databases_names():
|
||||
atomics[db_name] = transaction.atomic(using=db_name)
|
||||
atomics[db_name].__enter__()
|
||||
return atomics
|
||||
|
||||
@classmethod
|
||||
def _rollback_atomics(cls, atomics):
|
||||
"""Rollback atomic blocks opened through the previous method"""
|
||||
for db_name in reversed(cls._databases_names()):
|
||||
transaction.set_rollback(True, using=db_name)
|
||||
atomics[db_name].__exit__(None, None, None)
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestCase, cls).setUpClass()
|
||||
if not connections_support_transactions():
|
||||
return
|
||||
cls.cls_atomics = {}
|
||||
for db_name in cls._databases_names():
|
||||
cls.cls_atomics[db_name] = transaction.atomic(using=db_name)
|
||||
cls.cls_atomics[db_name].__enter__()
|
||||
cls.cls_atomics = cls._enter_atomics()
|
||||
|
||||
if cls.fixtures:
|
||||
for db_name in cls._databases_names(include_mirrors=False):
|
||||
try:
|
||||
call_command('loaddata', *cls.fixtures, **{
|
||||
'verbosity': 0,
|
||||
'commit': False,
|
||||
'database': db_name,
|
||||
})
|
||||
except Exception:
|
||||
cls._rollback_atomics(cls.cls_atomics)
|
||||
raise
|
||||
cls.setUpTestData()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
if connections_support_transactions():
|
||||
for db_name in reversed(cls._databases_names()):
|
||||
transaction.set_rollback(True, using=db_name)
|
||||
cls.cls_atomics[db_name].__exit__(None, None, None)
|
||||
cls._rollback_atomics(cls.cls_atomics)
|
||||
for conn in connections.all():
|
||||
conn.close()
|
||||
super(TestCase, cls).tearDownClass()
|
||||
|
@ -955,32 +977,12 @@ class TestCase(TransactionTestCase):
|
|||
return super(TestCase, self)._fixture_setup()
|
||||
|
||||
assert not self.reset_sequences, 'reset_sequences cannot be used on TestCase instances'
|
||||
|
||||
self.atomics = {}
|
||||
for db_name in self._databases_names():
|
||||
self.atomics[db_name] = transaction.atomic(using=db_name)
|
||||
self.atomics[db_name].__enter__()
|
||||
|
||||
for db_name in self._databases_names(include_mirrors=False):
|
||||
if self.fixtures:
|
||||
try:
|
||||
call_command('loaddata', *self.fixtures,
|
||||
**{
|
||||
'verbosity': 0,
|
||||
'commit': False,
|
||||
'database': db_name,
|
||||
})
|
||||
except Exception:
|
||||
self._fixture_teardown()
|
||||
raise
|
||||
self.atomics = self._enter_atomics()
|
||||
|
||||
def _fixture_teardown(self):
|
||||
if not connections_support_transactions():
|
||||
return super(TestCase, self)._fixture_teardown()
|
||||
|
||||
for db_name in reversed(self._databases_names()):
|
||||
transaction.set_rollback(True, using=db_name)
|
||||
self.atomics[db_name].__exit__(None, None, None)
|
||||
self._rollback_atomics(self.atomics)
|
||||
|
||||
|
||||
class CheckCondition(object):
|
||||
|
|
|
@ -67,6 +67,25 @@ to accept expressions other than aggregates. Aggregates are now able to
|
|||
reference multiple fields, as well as perform arithmetic, similar to ``F()``
|
||||
objects.
|
||||
|
||||
``TestCase`` data setup
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:class:`~django.test.TestCase` has been refactored to allow for data
|
||||
initialization at the class level using transactions and savepoints. Database
|
||||
backends which do not support transactions, like MySQL with the MyISAM storage
|
||||
engine, will still be able to run these tests but won't benefit from the
|
||||
improvements. Tests are now run within two nested
|
||||
:func:`~django.db.transaction.atomic()` blocks: one for the whole class and one
|
||||
for each test.
|
||||
|
||||
* The class method
|
||||
:meth:`TestCase.setUpTestData() <django.test.TestCase.setUpTestData>` adds
|
||||
the ability to setup test data at the class level. Using this technique can
|
||||
speed up the tests as compared to using ``setUp()``.
|
||||
|
||||
* Fixture loading within ``TestCase`` is now performed once for the whole
|
||||
``TestCase``.
|
||||
|
||||
Minor features
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -515,10 +534,6 @@ Tests
|
|||
* The :func:`~django.test.override_settings` decorator can now affect the
|
||||
master router in :setting:`DATABASE_ROUTERS`.
|
||||
|
||||
* Added the ability to setup test data at the class level using
|
||||
:meth:`TestCase.setUpTestData() <django.test.TestCase.setUpTestData>`. Using
|
||||
this technique can speed up the tests as compared to using ``setUp()``.
|
||||
|
||||
* Added test client support for file uploads with file-like objects.
|
||||
|
||||
Validators
|
||||
|
|
Loading…
Reference in New Issue