Skip to content

Commit 119154c

Browse files
Thomas Chaumenytimgraham
Thomas Chaumeny
authored andcommitted
Refs #20392 -- Load fixtures once within TestCase
1 parent 0dea81c commit 119154c

File tree

2 files changed

+50
-33
lines changed

2 files changed

+50
-33
lines changed

django/test/testcases.py

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -915,24 +915,46 @@ class TestCase(TransactionTestCase):
915915
On database backends with no transaction support, TestCase behaves as
916916
TransactionTestCase.
917917
"""
918+
@classmethod
919+
def _enter_atomics(cls):
920+
"""Helper method to open atomic blocks for multiple databases"""
921+
atomics = {}
922+
for db_name in cls._databases_names():
923+
atomics[db_name] = transaction.atomic(using=db_name)
924+
atomics[db_name].__enter__()
925+
return atomics
926+
927+
@classmethod
928+
def _rollback_atomics(cls, atomics):
929+
"""Rollback atomic blocks opened through the previous method"""
930+
for db_name in reversed(cls._databases_names()):
931+
transaction.set_rollback(True, using=db_name)
932+
atomics[db_name].__exit__(None, None, None)
918933

919934
@classmethod
920935
def setUpClass(cls):
921936
super(TestCase, cls).setUpClass()
922937
if not connections_support_transactions():
923938
return
924-
cls.cls_atomics = {}
925-
for db_name in cls._databases_names():
926-
cls.cls_atomics[db_name] = transaction.atomic(using=db_name)
927-
cls.cls_atomics[db_name].__enter__()
939+
cls.cls_atomics = cls._enter_atomics()
940+
941+
if cls.fixtures:
942+
for db_name in cls._databases_names(include_mirrors=False):
943+
try:
944+
call_command('loaddata', *cls.fixtures, **{
945+
'verbosity': 0,
946+
'commit': False,
947+
'database': db_name,
948+
})
949+
except Exception:
950+
cls._rollback_atomics(cls.cls_atomics)
951+
raise
928952
cls.setUpTestData()
929953

930954
@classmethod
931955
def tearDownClass(cls):
932956
if connections_support_transactions():
933-
for db_name in reversed(cls._databases_names()):
934-
transaction.set_rollback(True, using=db_name)
935-
cls.cls_atomics[db_name].__exit__(None, None, None)
957+
cls._rollback_atomics(cls.cls_atomics)
936958
for conn in connections.all():
937959
conn.close()
938960
super(TestCase, cls).tearDownClass()
@@ -955,32 +977,12 @@ def _fixture_setup(self):
955977
return super(TestCase, self)._fixture_setup()
956978

957979
assert not self.reset_sequences, 'reset_sequences cannot be used on TestCase instances'
958-
959-
self.atomics = {}
960-
for db_name in self._databases_names():
961-
self.atomics[db_name] = transaction.atomic(using=db_name)
962-
self.atomics[db_name].__enter__()
963-
964-
for db_name in self._databases_names(include_mirrors=False):
965-
if self.fixtures:
966-
try:
967-
call_command('loaddata', *self.fixtures,
968-
**{
969-
'verbosity': 0,
970-
'commit': False,
971-
'database': db_name,
972-
})
973-
except Exception:
974-
self._fixture_teardown()
975-
raise
980+
self.atomics = self._enter_atomics()
976981

977982
def _fixture_teardown(self):
978983
if not connections_support_transactions():
979984
return super(TestCase, self)._fixture_teardown()
980-
981-
for db_name in reversed(self._databases_names()):
982-
transaction.set_rollback(True, using=db_name)
983-
self.atomics[db_name].__exit__(None, None, None)
985+
self._rollback_atomics(self.atomics)
984986

985987

986988
class CheckCondition(object):

docs/releases/1.8.txt

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,25 @@ to accept expressions other than aggregates. Aggregates are now able to
6767
reference multiple fields, as well as perform arithmetic, similar to ``F()``
6868
objects.
6969

70+
``TestCase`` data setup
71+
~~~~~~~~~~~~~~~~~~~~~~~
72+
73+
:class:`~django.test.TestCase` has been refactored to allow for data
74+
initialization at the class level using transactions and savepoints. Database
75+
backends which do not support transactions, like MySQL with the MyISAM storage
76+
engine, will still be able to run these tests but won't benefit from the
77+
improvements. Tests are now run within two nested
78+
:func:`~django.db.transaction.atomic()` blocks: one for the whole class and one
79+
for each test.
80+
81+
* The class method
82+
:meth:`TestCase.setUpTestData() <django.test.TestCase.setUpTestData>` adds
83+
the ability to setup test data at the class level. Using this technique can
84+
speed up the tests as compared to using ``setUp()``.
85+
86+
* Fixture loading within ``TestCase`` is now performed once for the whole
87+
``TestCase``.
88+
7089
Minor features
7190
~~~~~~~~~~~~~~
7291

@@ -515,10 +534,6 @@ Tests
515534
* The :func:`~django.test.override_settings` decorator can now affect the
516535
master router in :setting:`DATABASE_ROUTERS`.
517536

518-
* Added the ability to setup test data at the class level using
519-
:meth:`TestCase.setUpTestData() <django.test.TestCase.setUpTestData>`. Using
520-
this technique can speed up the tests as compared to using ``setUp()``.
521-
522537
* Added test client support for file uploads with file-like objects.
523538

524539
Validators

0 commit comments

Comments
 (0)