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
|
On database backends with no transaction support, TestCase behaves as
|
||||||
TransactionTestCase.
|
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
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
super(TestCase, cls).setUpClass()
|
super(TestCase, cls).setUpClass()
|
||||||
if not connections_support_transactions():
|
if not connections_support_transactions():
|
||||||
return
|
return
|
||||||
cls.cls_atomics = {}
|
cls.cls_atomics = cls._enter_atomics()
|
||||||
for db_name in cls._databases_names():
|
|
||||||
cls.cls_atomics[db_name] = transaction.atomic(using=db_name)
|
if cls.fixtures:
|
||||||
cls.cls_atomics[db_name].__enter__()
|
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()
|
cls.setUpTestData()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def tearDownClass(cls):
|
def tearDownClass(cls):
|
||||||
if connections_support_transactions():
|
if connections_support_transactions():
|
||||||
for db_name in reversed(cls._databases_names()):
|
cls._rollback_atomics(cls.cls_atomics)
|
||||||
transaction.set_rollback(True, using=db_name)
|
|
||||||
cls.cls_atomics[db_name].__exit__(None, None, None)
|
|
||||||
for conn in connections.all():
|
for conn in connections.all():
|
||||||
conn.close()
|
conn.close()
|
||||||
super(TestCase, cls).tearDownClass()
|
super(TestCase, cls).tearDownClass()
|
||||||
|
@ -955,32 +977,12 @@ class TestCase(TransactionTestCase):
|
||||||
return super(TestCase, self)._fixture_setup()
|
return super(TestCase, self)._fixture_setup()
|
||||||
|
|
||||||
assert not self.reset_sequences, 'reset_sequences cannot be used on TestCase instances'
|
assert not self.reset_sequences, 'reset_sequences cannot be used on TestCase instances'
|
||||||
|
self.atomics = self._enter_atomics()
|
||||||
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
|
|
||||||
|
|
||||||
def _fixture_teardown(self):
|
def _fixture_teardown(self):
|
||||||
if not connections_support_transactions():
|
if not connections_support_transactions():
|
||||||
return super(TestCase, self)._fixture_teardown()
|
return super(TestCase, self)._fixture_teardown()
|
||||||
|
self._rollback_atomics(self.atomics)
|
||||||
for db_name in reversed(self._databases_names()):
|
|
||||||
transaction.set_rollback(True, using=db_name)
|
|
||||||
self.atomics[db_name].__exit__(None, None, None)
|
|
||||||
|
|
||||||
|
|
||||||
class CheckCondition(object):
|
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()``
|
reference multiple fields, as well as perform arithmetic, similar to ``F()``
|
||||||
objects.
|
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
|
Minor features
|
||||||
~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -515,10 +534,6 @@ Tests
|
||||||
* The :func:`~django.test.override_settings` decorator can now affect the
|
* The :func:`~django.test.override_settings` decorator can now affect the
|
||||||
master router in :setting:`DATABASE_ROUTERS`.
|
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.
|
* Added test client support for file uploads with file-like objects.
|
||||||
|
|
||||||
Validators
|
Validators
|
||||||
|
|
Loading…
Reference in New Issue