summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Chaumeny <thomas.chaumeny@polyconseil.fr>2014-12-04 14:05:59 +0100
committerTim Graham <timograham@gmail.com>2014-12-12 09:16:15 -0500
commit119154ca7f65d423bb742aa0e32ffcfcb21d4b87 (patch)
tree139d0431aeffca74686aea53c6dda99f9a26c460
parent0dea81cd6d34b3e41cc4bbec99b5fdf06142b09e (diff)
Refs #20392 -- Load fixtures once within TestCase
-rw-r--r--django/test/testcases.py60
-rw-r--r--docs/releases/1.8.txt23
2 files changed, 50 insertions, 33 deletions
diff --git a/django/test/testcases.py b/django/test/testcases.py
index 78c185ecd8..38bbd40946 100644
--- a/django/test/testcases.py
+++ b/django/test/testcases.py
@@ -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):
diff --git a/docs/releases/1.8.txt b/docs/releases/1.8.txt
index 5ab42996ab..f9eaf83148 100644
--- a/docs/releases/1.8.txt
+++ b/docs/releases/1.8.txt
@@ -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