|
@@ -1,7 +1,11 @@
|
|
|
+from functools import wraps
|
|
|
+
|
|
|
from django.db import IntegrityError, connections, transaction
|
|
|
-from django.test import TestCase, skipUnlessDBFeature
|
|
|
+from django.test import TestCase, ignore_warnings, skipUnlessDBFeature
|
|
|
+from django.test.testcases import TestData
|
|
|
+from django.utils.deprecation import RemovedInDjango41Warning
|
|
|
|
|
|
-from .models import Car, PossessedCar
|
|
|
+from .models import Car, Person, PossessedCar
|
|
|
|
|
|
|
|
|
class TestTestCase(TestCase):
|
|
@@ -38,3 +42,95 @@ class TestTestCase(TestCase):
|
|
|
)
|
|
|
with self.assertRaisesMessage(AssertionError, message):
|
|
|
Car.objects.using('other').get()
|
|
|
+
|
|
|
+
|
|
|
+class NonDeepCopyAble:
|
|
|
+ def __deepcopy__(self, memo):
|
|
|
+ raise TypeError
|
|
|
+
|
|
|
+
|
|
|
+def assert_no_queries(test):
|
|
|
+ @wraps(test)
|
|
|
+ def inner(self):
|
|
|
+ with self.assertNumQueries(0):
|
|
|
+ test(self)
|
|
|
+ return inner
|
|
|
+
|
|
|
+
|
|
|
+class TestDataTests(TestCase):
|
|
|
+ # setUpTestData re-assignment are also wrapped in TestData.
|
|
|
+ jim_douglas = None
|
|
|
+
|
|
|
+ @classmethod
|
|
|
+ def setUpTestData(cls):
|
|
|
+ cls.jim_douglas = Person.objects.create(name='Jim Douglas')
|
|
|
+ cls.car = Car.objects.create(name='1963 Volkswagen Beetle')
|
|
|
+ cls.herbie = cls.jim_douglas.possessed_cars.create(
|
|
|
+ car=cls.car,
|
|
|
+ belongs_to=cls.jim_douglas,
|
|
|
+ )
|
|
|
+ cls.non_deepcopy_able = NonDeepCopyAble()
|
|
|
+
|
|
|
+ @assert_no_queries
|
|
|
+ def test_class_attribute_equality(self):
|
|
|
+ """Class level test data is equal to instance level test data."""
|
|
|
+ self.assertEqual(self.jim_douglas, self.__class__.jim_douglas)
|
|
|
+
|
|
|
+ @assert_no_queries
|
|
|
+ def test_class_attribute_identity(self):
|
|
|
+ """
|
|
|
+ Class level test data is not identical to instance level test data.
|
|
|
+ """
|
|
|
+ self.assertIsNot(self.jim_douglas, self.__class__.jim_douglas)
|
|
|
+
|
|
|
+ @assert_no_queries
|
|
|
+ def test_identity_preservation(self):
|
|
|
+ """Identity of test data is preserved between accesses."""
|
|
|
+ self.assertIs(self.jim_douglas, self.jim_douglas)
|
|
|
+
|
|
|
+ @assert_no_queries
|
|
|
+ def test_known_related_objects_identity_preservation(self):
|
|
|
+ """Known related objects identity is preserved."""
|
|
|
+ self.assertIs(self.herbie.car, self.car)
|
|
|
+ self.assertIs(self.herbie.belongs_to, self.jim_douglas)
|
|
|
+
|
|
|
+ @ignore_warnings(category=RemovedInDjango41Warning)
|
|
|
+ def test_undeepcopyable(self):
|
|
|
+ self.assertIs(self.non_deepcopy_able, self.__class__.non_deepcopy_able)
|
|
|
+
|
|
|
+ def test_undeepcopyable_warning(self):
|
|
|
+ msg = (
|
|
|
+ "Assigning objects which don't support copy.deepcopy() during "
|
|
|
+ "setUpTestData() is deprecated. Either assign the "
|
|
|
+ "non_deepcopy_able attribute during setUpClass() or setUp(), or "
|
|
|
+ "add support for deepcopy() to "
|
|
|
+ "test_utils.test_testcase.TestDataTests.non_deepcopy_able."
|
|
|
+ )
|
|
|
+ with self.assertRaisesMessage(RemovedInDjango41Warning, msg):
|
|
|
+ self.non_deepcopy_able
|
|
|
+
|
|
|
+ def test_repr(self):
|
|
|
+ self.assertEqual(
|
|
|
+ repr(TestData('attr', 'value')),
|
|
|
+ "<TestData: name='attr', data='value'>",
|
|
|
+ )
|
|
|
+
|
|
|
+
|
|
|
+class SetupTestDataIsolationTests(TestCase):
|
|
|
+ """
|
|
|
+ In-memory data isolation is respected for model instances assigned to class
|
|
|
+ attributes during setUpTestData.
|
|
|
+ """
|
|
|
+ @classmethod
|
|
|
+ def setUpTestData(cls):
|
|
|
+ cls.car = Car.objects.create(name='Volkswagen Beetle')
|
|
|
+
|
|
|
+ def test_book_name_deutsh(self):
|
|
|
+ self.assertEqual(self.car.name, 'Volkswagen Beetle')
|
|
|
+ self.car.name = 'VW sKäfer'
|
|
|
+ self.car.save()
|
|
|
+
|
|
|
+ def test_book_name_french(self):
|
|
|
+ self.assertEqual(self.car.name, 'Volkswagen Beetle')
|
|
|
+ self.car.name = 'Volkswagen Coccinelle'
|
|
|
+ self.car.save()
|