diff options
Diffstat (limited to 'django/test')
| -rw-r--r-- | django/test/runner.py | 22 | ||||
| -rw-r--r-- | django/test/testcases.py | 29 |
2 files changed, 37 insertions, 14 deletions
diff --git a/django/test/runner.py b/django/test/runner.py index ed969cc42f..aa2b269fab 100644 --- a/django/test/runner.py +++ b/django/test/runner.py @@ -11,7 +11,7 @@ from io import StringIO from django.core.management import call_command from django.db import connections -from django.test import SimpleTestCase, TestCase +from django.test import SimpleTestCase, TestCase, TransactionTestCase from django.test.utils import ( setup_databases as _setup_databases, setup_test_environment, teardown_databases as _teardown_databases, teardown_test_environment, @@ -399,7 +399,7 @@ class DiscoverRunner: parallel_test_suite = ParallelTestSuite test_runner = unittest.TextTestRunner test_loader = unittest.defaultTestLoader - reorder_by = (TestCase, SimpleTestCase) + reorder_by = (TestCase, TransactionTestCase, SimpleTestCase) def __init__(self, pattern=None, top_level=None, verbosity=1, interactive=True, failfast=False, keepdb=False, @@ -637,6 +637,22 @@ def is_discoverable(label): return os.path.isdir(os.path.abspath(label)) +def reorder_postprocess(reordered_suite): + """ + To make TransactionTestCases initialize their data properly, they must know + if the next TransactionTestCase needs initial data migrations serialized in + the connection. Initialize _next_serialized_rollback attribute depending on + the serialized_rollback option present in the next test class in the suite. + If the next test has no serialized_rollback attribute, it means there + aren't any more TransactionTestCases. + """ + for previous_test, next_test in zip(reordered_suite._tests[:-1], reordered_suite._tests[1:]): + next_serialized_rollback = getattr(next_test, 'serialized_rollback', None) + if next_serialized_rollback is not None: + previous_test._next_serialized_rollback = next_serialized_rollback + return reordered_suite + + def reorder_suite(suite, classes, reverse=False): """ Reorder a test suite by test type. @@ -656,7 +672,7 @@ def reorder_suite(suite, classes, reverse=False): reordered_suite = suite_class() for i in range(class_count + 1): reordered_suite.addTests(bins[i]) - return reordered_suite + return reorder_postprocess(reordered_suite) def partition_suite_by_type(suite, classes, bins, reverse=False): diff --git a/django/test/testcases.py b/django/test/testcases.py index 2c358c01af..9f549f626f 100644 --- a/django/test/testcases.py +++ b/django/test/testcases.py @@ -827,6 +827,15 @@ class TransactionTestCase(SimpleTestCase): # This can be slow; this flag allows enabling on a per-case basis. serialized_rollback = False + # This attribute is strongly linked to serialized_rollback parameter and + # allows the data restoration after the database flush, at the end of the + # test, if the next test needs the initial data. This attribute is updated + # by the test runner when the test suite is built. Being initialized to + # True is crucial: the last TransactionTestCase, which doesn't have any + # test classes with the serialized_rollback attribute, will always have + # this value set to True. + _next_serialized_rollback = True + # Since tests will be wrapped in a transaction, or serialized if they # are not available, we allow queries to be run. allow_database_queries = True @@ -897,17 +906,6 @@ class TransactionTestCase(SimpleTestCase): if self.reset_sequences: self._reset_sequences(db_name) - # If we need to provide replica initial data from migrated apps, - # then do so. - if self.serialized_rollback and hasattr(connections[db_name], "_test_serialized_contents"): - if self.available_apps is not None: - apps.unset_available_apps() - connections[db_name].creation.deserialize_db_from_string( - connections[db_name]._test_serialized_contents - ) - if self.available_apps is not None: - apps.set_available_apps(self.available_apps) - if self.fixtures: # We have to use this slightly awkward syntax due to the fact # that we're using *args and **kwargs together. @@ -961,6 +959,15 @@ class TransactionTestCase(SimpleTestCase): database=db_name, reset_sequences=False, allow_cascade=self.available_apps is not None, inhibit_post_migrate=inhibit_post_migrate) + # Provide replica initial data from migrated apps, if needed. + if self._next_serialized_rollback and hasattr(connections[db_name], '_test_serialized_contents'): + if self.available_apps is not None: + apps.unset_available_apps() + connections[db_name].creation.deserialize_db_from_string( + connections[db_name]._test_serialized_contents + ) + if self.available_apps is not None: + apps.set_available_apps(self.available_apps) def assertQuerysetEqual(self, qs, values, transform=repr, ordered=True, msg=None): items = map(transform, qs) |
