mirror of https://github.com/django/django.git
Fixed #11665 -- Made TestCase check deferrable constraints after each test.
This commit is contained in:
parent
a6f856df52
commit
fcd08c1757
|
@ -1044,8 +1044,19 @@ class TestCase(TransactionTestCase):
|
||||||
def _fixture_teardown(self):
|
def _fixture_teardown(self):
|
||||||
if not connections_support_transactions():
|
if not connections_support_transactions():
|
||||||
return super(TestCase, self)._fixture_teardown()
|
return super(TestCase, self)._fixture_teardown()
|
||||||
|
try:
|
||||||
|
for db_name in reversed(self._databases_names()):
|
||||||
|
if self._should_check_constraints(connections[db_name]):
|
||||||
|
connections[db_name].check_constraints()
|
||||||
|
finally:
|
||||||
self._rollback_atomics(self.atomics)
|
self._rollback_atomics(self.atomics)
|
||||||
|
|
||||||
|
def _should_check_constraints(self, connection):
|
||||||
|
return (
|
||||||
|
connection.features.can_defer_constraint_checks and
|
||||||
|
not connection.needs_rollback and connection.is_usable()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class CheckCondition(object):
|
class CheckCondition(object):
|
||||||
"""Descriptor class for deferred condition checking"""
|
"""Descriptor class for deferred condition checking"""
|
||||||
|
|
|
@ -333,7 +333,8 @@ Templates
|
||||||
Tests
|
Tests
|
||||||
~~~~~
|
~~~~~
|
||||||
|
|
||||||
* ...
|
* To better catch bugs, :class:`~django.test.TestCase` now checks deferrable
|
||||||
|
database constraints at the end of each test.
|
||||||
|
|
||||||
URLs
|
URLs
|
||||||
~~~~
|
~~~~
|
||||||
|
@ -541,6 +542,9 @@ Miscellaneous
|
||||||
aggregate function now returns a ``float`` instead of ``decimal.Decimal``.
|
aggregate function now returns a ``float`` instead of ``decimal.Decimal``.
|
||||||
(It's still wrapped in a measure of square meters.)
|
(It's still wrapped in a measure of square meters.)
|
||||||
|
|
||||||
|
* Tests that violate deferrable database constraints will now error when run on
|
||||||
|
a database that supports deferrable constraints.
|
||||||
|
|
||||||
.. _deprecated-features-1.10:
|
.. _deprecated-features-1.10:
|
||||||
|
|
||||||
Features deprecated in 1.10
|
Features deprecated in 1.10
|
||||||
|
|
|
@ -761,11 +761,18 @@ additions, including:
|
||||||
* Wraps the tests within two nested ``atomic`` blocks: one for the whole class
|
* Wraps the tests within two nested ``atomic`` blocks: one for the whole class
|
||||||
and one for each test.
|
and one for each test.
|
||||||
|
|
||||||
|
* Checks deferrable database constraints at the end of each test.
|
||||||
|
|
||||||
* Creates a TestClient instance.
|
* Creates a TestClient instance.
|
||||||
|
|
||||||
* Django-specific assertions for testing for things like redirection and form
|
* Django-specific assertions for testing for things like redirection and form
|
||||||
errors.
|
errors.
|
||||||
|
|
||||||
|
.. versionchanged:: 1.10
|
||||||
|
|
||||||
|
The check for deferrable database constraints at the end of each test was
|
||||||
|
added.
|
||||||
|
|
||||||
.. classmethod:: TestCase.setUpTestData()
|
.. classmethod:: TestCase.setUpTestData()
|
||||||
|
|
||||||
The class-level ``atomic`` block described above allows the creation of
|
The class-level ``atomic`` block described above allows the creation of
|
||||||
|
|
|
@ -991,3 +991,9 @@ class UUIDUserTests(TestCase):
|
||||||
self.assertEqual(row.user_id, 1) # hardcoded in CustomUserAdmin.log_change()
|
self.assertEqual(row.user_id, 1) # hardcoded in CustomUserAdmin.log_change()
|
||||||
self.assertEqual(row.object_id, str(u.pk))
|
self.assertEqual(row.object_id, str(u.pk))
|
||||||
self.assertEqual(row.get_change_message(), 'Changed password.')
|
self.assertEqual(row.get_change_message(), 'Changed password.')
|
||||||
|
|
||||||
|
# The LogEntry.user column isn't altered to a UUID type so it's set to
|
||||||
|
# an integer manually in CustomUserAdmin to avoid an error. To avoid a
|
||||||
|
# constraint error, delete the entry before constraints are checked
|
||||||
|
# after the test.
|
||||||
|
row.delete()
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
from django.db import IntegrityError, transaction
|
||||||
|
from django.test import TestCase, skipUnlessDBFeature
|
||||||
|
|
||||||
|
from .models import PossessedCar
|
||||||
|
|
||||||
|
|
||||||
|
class TestTestCase(TestCase):
|
||||||
|
|
||||||
|
@skipUnlessDBFeature('can_defer_constraint_checks')
|
||||||
|
@skipUnlessDBFeature('supports_foreign_keys')
|
||||||
|
def test_fixture_teardown_checks_constraints(self):
|
||||||
|
rollback_atomics = self._rollback_atomics
|
||||||
|
self._rollback_atomics = lambda connection: None # noop
|
||||||
|
try:
|
||||||
|
car = PossessedCar.objects.create(car_id=1, belongs_to_id=1)
|
||||||
|
with self.assertRaises(IntegrityError), transaction.atomic():
|
||||||
|
self._fixture_teardown()
|
||||||
|
car.delete()
|
||||||
|
finally:
|
||||||
|
self._rollback_atomics = rollback_atomics
|
Loading…
Reference in New Issue