Commit fcd08c17 authored by Jon Dufresne's avatar Jon Dufresne Committed by Tim Graham
Browse files

Fixed #11665 -- Made TestCase check deferrable constraints after each test.

parent a6f856df
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
@@ -1044,8 +1044,19 @@ class TestCase(TransactionTestCase):
    def _fixture_teardown(self):
        if not connections_support_transactions():
            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)

    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):
    """Descriptor class for deferred condition checking"""
+5 −1
Original line number Diff line number Diff line
@@ -333,7 +333,8 @@ Templates
Tests
~~~~~

* ...
* To better catch bugs, :class:`~django.test.TestCase` now checks deferrable
  database constraints at the end of each test.

URLs
~~~~
@@ -541,6 +542,9 @@ Miscellaneous
  aggregate function now returns a ``float`` instead of ``decimal.Decimal``.
  (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:

Features deprecated in 1.10
+7 −0
Original line number Diff line number Diff line
@@ -761,11 +761,18 @@ additions, including:
* Wraps the tests within two nested ``atomic`` blocks: one for the whole class
  and one for each test.

* Checks deferrable database constraints at the end of each test.

* Creates a TestClient instance.

* Django-specific assertions for testing for things like redirection and form
  errors.

.. versionchanged:: 1.10

    The check for deferrable database constraints at the end of each test was
    added.

.. classmethod:: TestCase.setUpTestData()

    The class-level ``atomic`` block described above allows the creation of
+6 −0
Original line number Diff line number Diff line
@@ -991,3 +991,9 @@ class UUIDUserTests(TestCase):
        self.assertEqual(row.user_id, 1)  # hardcoded in CustomUserAdmin.log_change()
        self.assertEqual(row.object_id, str(u.pk))
        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()
+20 −0
Original line number Diff line number Diff line
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