Reverted "Fixed #25251 -- Made data migrations available in TransactionTestCase when using --keepdb."

This reverts commits b3b1d3d45f and
9fa0d3786f due to reverse build failures
for which a solution isn't forthcoming.
This commit is contained in:
Tim Graham 2018-12-05 15:21:09 -05:00
parent 734ce71824
commit 4c7c608a1d
8 changed files with 14 additions and 225 deletions

View File

@ -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, TransactionTestCase
from django.test import SimpleTestCase, TestCase
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, TransactionTestCase, SimpleTestCase)
reorder_by = (TestCase, SimpleTestCase)
def __init__(self, pattern=None, top_level=None, verbosity=1,
interactive=True, failfast=False, keepdb=False,
@ -637,27 +637,6 @@ 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.
"""
# Filter out skipped tests.
active_tests = [
test for test in reordered_suite._tests
if not getattr(test, '__unittest_skip__', False)
]
for previous_test, next_test in zip(active_tests[:-1], active_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.
@ -677,7 +656,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 reorder_postprocess(reordered_suite)
return reordered_suite
def partition_suite_by_type(suite, classes, bins, reverse=False):

View File

@ -827,15 +827,6 @@ 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
@ -906,6 +897,16 @@ class TransactionTestCase(SimpleTestCase):
if self.reset_sequences:
self._reset_sequences(db_name)
# Provide replica initial data from migrated apps, if needed.
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.
@ -959,15 +960,6 @@ 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)

View File

@ -777,11 +777,6 @@ the database state between tests if you don't have transactions). You can set
this to ``False`` to speed up creation time if you don't have any test classes
with :ref:`serialized_rollback=True <test-case-serialized-rollback>`.
Don't set this to ``False`` if you want to use :option:`test --keepdb`
and your test suite contains :class:`~django.test.TransactionTestCase` or
doesn't support transactions, as this in-memory JSON string is used to restore
the initial data migrations in these situations.
.. setting:: TEST_TEMPLATE
``TEMPLATE``

View File

@ -1,50 +0,0 @@
from unittest import TestCase
from django.test import (
TestCase as DjangoTestCase, TransactionTestCase, skipUnlessDBFeature,
)
class TestVanillaUnittest(TestCase):
def test_sample(self):
self.assertEqual(1, 1)
class TestDjangoTestCase(DjangoTestCase):
def test_sample(self):
self.assertEqual(1, 1)
class TestTransactionTestCase1(TransactionTestCase):
available_apps = ['test_discovery_sample3']
serialized_rollback = False
def test_sample(self):
self.assertEqual(1, 1)
class TestTransactionTestCase2(TransactionTestCase):
available_apps = ['test_discovery_sample3']
serialized_rollback = True
def test_sample(self):
self.assertEqual(1, 1)
# django.test.runner.reorder_postprocess() ignores this skipped test when
# assigning _next_serialized_rollback.
@skipUnlessDBFeature('nonexistent')
class TestTransactionTestCase3(TransactionTestCase):
available_apps = ['test_discovery_sample3']
serialized_rollback = True
def test_sample(self):
self.assertEqual(1, 1)
class TestTransactionTestCase4(TransactionTestCase):
available_apps = ['test_discovery_sample3']
serialized_rollback = False
def test_sample(self):
self.assertEqual(1, 1)

View File

@ -1,28 +0,0 @@
from unittest import TestCase
from django.test import (
SimpleTestCase, TestCase as DjangoTestCase, TransactionTestCase,
)
class TestDjangoTestCase(DjangoTestCase):
def test_sample(self):
self.assertEqual(1, 1)
class TestVanillaUnittest(TestCase):
def test_sample(self):
self.assertEqual(1, 1)
class TestZimpleTestCase(SimpleTestCase):
# Z gets this test to appear after Vanilla in the default suite.
def test_sample(self):
self.assertEqual(1, 1)
class TestTransactionTestCase(TransactionTestCase):
available_apps = ['test_discovery_sample3']
def test_sample(self):
self.assertEqual(1, 1)

View File

@ -223,32 +223,3 @@ class DiscoverRunnerTests(SimpleTestCase):
with captured_stdout() as stdout:
runner.build_suite(['test_runner_apps.tagged.tests'])
self.assertIn('Excluding test tag(s): bar, foo.\n', stdout.getvalue())
def test_transaction_test_case_before_simple_test_case(self):
runner = DiscoverRunner()
suite = runner.build_suite(['test_discovery_sample3.tests_transaction_test_case_ordering'])
suite = tuple(suite)
# TransactionTestCase is second after TestCase.
self.assertIn('TestTransactionTestCase', suite[1].id())
def test_transaction_test_case_next_serialized_rollback_option(self):
runner = DiscoverRunner()
suite = runner.build_suite(['test_discovery_sample3.tests_transaction_test_case_mixed'])
django_test_case, first_transaction_test_case, second_transaction_test_case, \
third_transaction_test_case, fourth_transaction_test_case, vanilla_test_case = suite
# TransactionTestCase1._next_serialized_rollback is
# TransactionTestCase2.serialize_rollback.
self.assertEqual(
first_transaction_test_case._next_serialized_rollback,
second_transaction_test_case.serialized_rollback
)
# TransactionTestCase2._next_serialized_rollback is
# TransactionTestCase4.serialize_rollback because TransactionTestCase3
# is skipped.
self.assertEqual(
second_transaction_test_case._next_serialized_rollback,
fourth_transaction_test_case.serialized_rollback
)
# The last TransactionTestCase of the suite has
# _next_serialized_rollback = True.
self.assertIs(fourth_transaction_test_case._next_serialized_rollback, True)

View File

@ -1,44 +1,10 @@
import json
from unittest import mock
from django.apps import apps
from django.db import connections
from django.test import TestCase, TransactionTestCase, override_settings
from .models import Car
class TestSerializedContentMockMixin:
"""
Use this mixin on each test involving TransactionTestCase and
serialized_rollback = True option to avoid test dependencies. It mocks what
would be serialized after initial data migrations and restores it at the
end of the test.
"""
initial_data_migration = '[]'
_connections_test_serialized_content = {}
def _pre_setup(self):
for db_name in self._databases_names(include_mirrors=False):
self._connections_test_serialized_content[db_name] = connections[db_name]._test_serialized_contents
connections[db_name]._test_serialized_contents = self.initial_data_migration
super()._pre_setup()
def _post_teardown(self):
super()._post_teardown()
for db_name in self._databases_names(include_mirrors=False):
connections[db_name]._test_serialized_contents = self._connections_test_serialized_content[db_name]
@classmethod
def tearDownClass(cls):
super().tearDownClass()
# Clean up any data that has been created by the class.
for data in json.loads(cls.initial_data_migration):
model = apps.get_model(*data['model'].split('.'))
model.objects.filter(pk=data['pk']).delete()
class TestSerializedRollbackInhibitsPostMigrate(TestSerializedContentMockMixin, TransactionTestCase):
class TestSerializedRollbackInhibitsPostMigrate(TransactionTestCase):
"""
TransactionTestCase._fixture_teardown() inhibits the post_migrate signal
for test classes with serialized_rollback=True.
@ -78,39 +44,3 @@ class TransactionTestCaseMultiDbTests(TestCase):
"""
for alias in connections:
self.assertEqual(len(connections[alias].queries_log), 0, 'Failed for alias %s' % alias)
class TestDataRestoredOnTearDownIfSerializedRollback(TestSerializedContentMockMixin, TransactionTestCase):
"""
Initial data is recreated in TransactionTestCase._fixture_teardown()
after the database is flushed so it's available in next test.
"""
available_apps = ['test_utils']
_next_serialized_rollback = True
initial_data_migration = '[{"model": "test_utils.car", "pk": 666, "fields": {"name": "K 2000"}}]'
def _post_teardown(self):
super()._post_teardown()
# Won't be True if running the tests with --reverse.
if self._next_serialized_rollback:
self.assertTrue(Car.objects.exists())
def test(self):
pass # Should be the only one in this class.
class TestDataNotRestoredOnTearDownIfNotSerializedRollback(TestSerializedContentMockMixin, TransactionTestCase):
"""
Initial data isn't recreated in TransactionTestCase._fixture_teardown()
if _next_serialized_rollback is False.
"""
available_apps = ['test_utils']
_next_serialized_rollback = False
initial_data_migration = '[{"model": "test_utils.car", "pk": 666, "fields": {"name": "K 2000"}}]'
def _post_teardown(self):
super()._post_teardown()
self.assertFalse(Car.objects.exists())
def test(self):
pass # Should be the only one in this class.