mirror of
https://github.com/django/django.git
synced 2025-10-23 21:59:11 +00:00
Fixed #25251 -- Made data migrations available in TransactionTestCase when using --keepdb.
Data loaded in migrations were restored at the beginning of each TransactionTestCase and all the tables are truncated at the end of these test cases. If there was a TransactionTestCase at the end of the test suite, the migrated data weren't restored in the database (especially unexpected when using --keepdb). Now data is restored at the end of each TransactionTestCase.
This commit is contained in:
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user