2018-11-24 10:22:09 +08:00
|
|
|
from functools import wraps
|
|
|
|
|
2019-01-13 03:33:50 +08:00
|
|
|
from django.db import IntegrityError, connections, transaction
|
2021-09-16 14:09:52 +08:00
|
|
|
from django.test import TestCase, skipUnlessDBFeature
|
2021-11-13 01:36:13 +08:00
|
|
|
from django.test.testcases import DatabaseOperationForbidden, TestData
|
2016-02-13 08:41:31 +08:00
|
|
|
|
2018-11-24 10:22:09 +08:00
|
|
|
from .models import Car, Person, PossessedCar
|
2016-02-13 08:41:31 +08:00
|
|
|
|
|
|
|
|
|
|
|
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
|
2018-07-12 12:12:20 +08:00
|
|
|
|
2019-01-13 03:33:50 +08:00
|
|
|
def test_disallowed_database_connection(self):
|
|
|
|
message = (
|
|
|
|
"Database connections to 'other' are not allowed in this test. "
|
|
|
|
"Add 'other' to test_utils.test_testcase.TestTestCase.databases to "
|
|
|
|
"ensure proper test isolation and silence this failure."
|
|
|
|
)
|
2021-11-13 01:36:13 +08:00
|
|
|
with self.assertRaisesMessage(DatabaseOperationForbidden, message):
|
2019-01-13 03:33:50 +08:00
|
|
|
connections["other"].connect()
|
2021-11-13 01:36:13 +08:00
|
|
|
with self.assertRaisesMessage(DatabaseOperationForbidden, message):
|
2019-01-13 03:33:50 +08:00
|
|
|
connections["other"].temporary_connection()
|
|
|
|
|
2018-07-12 12:12:20 +08:00
|
|
|
def test_disallowed_database_queries(self):
|
|
|
|
message = (
|
|
|
|
"Database queries to 'other' are not allowed in this test. "
|
|
|
|
"Add 'other' to test_utils.test_testcase.TestTestCase.databases to "
|
|
|
|
"ensure proper test isolation and silence this failure."
|
|
|
|
)
|
2021-11-13 01:36:13 +08:00
|
|
|
with self.assertRaisesMessage(DatabaseOperationForbidden, message):
|
2018-07-12 12:12:20 +08:00
|
|
|
Car.objects.using("other").get()
|
2018-11-24 10:22:09 +08:00
|
|
|
|
2022-04-12 16:54:17 +08:00
|
|
|
@skipUnlessDBFeature("supports_transactions")
|
2021-07-03 01:33:48 +08:00
|
|
|
def test_reset_sequences(self):
|
|
|
|
old_reset_sequences = self.reset_sequences
|
|
|
|
self.reset_sequences = True
|
|
|
|
msg = "reset_sequences cannot be used on TestCase instances"
|
|
|
|
try:
|
|
|
|
with self.assertRaisesMessage(TypeError, msg):
|
|
|
|
self._fixture_setup()
|
|
|
|
finally:
|
|
|
|
self.reset_sequences = old_reset_sequences
|
|
|
|
|
2018-11-24 10:22:09 +08:00
|
|
|
|
|
|
|
def assert_no_queries(test):
|
|
|
|
@wraps(test)
|
|
|
|
def inner(self):
|
|
|
|
with self.assertNumQueries(0):
|
|
|
|
test(self)
|
2022-02-04 03:24:19 +08:00
|
|
|
|
2018-11-24 10:22:09 +08:00
|
|
|
return inner
|
|
|
|
|
|
|
|
|
2022-04-12 16:54:17 +08:00
|
|
|
# On databases with no transaction support (for instance, MySQL with the MyISAM
|
|
|
|
# engine), setUpTestData() is called before each test, so there is no need to
|
|
|
|
# clone class level test data.
|
|
|
|
@skipUnlessDBFeature("supports_transactions")
|
2018-11-24 10:22:09 +08:00
|
|
|
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,
|
|
|
|
)
|
|
|
|
|
2021-12-03 18:56:22 +08:00
|
|
|
cls.person_binary = Person.objects.create(name="Person", data=b"binary data")
|
|
|
|
cls.person_binary_get = Person.objects.get(pk=cls.person_binary.pk)
|
|
|
|
|
2018-11-24 10:22:09 +08:00
|
|
|
@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)
|
2021-12-03 18:56:22 +08:00
|
|
|
self.assertEqual(self.person_binary, self.__class__.person_binary)
|
|
|
|
self.assertEqual(self.person_binary_get, self.__class__.person_binary_get)
|
2018-11-24 10:22:09 +08:00
|
|
|
|
|
|
|
@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)
|
2021-12-03 18:56:22 +08:00
|
|
|
self.assertIsNot(self.person_binary, self.__class__.person_binary)
|
|
|
|
self.assertIsNot(self.person_binary_get, self.__class__.person_binary_get)
|
|
|
|
|
|
|
|
@assert_no_queries
|
|
|
|
def test_binaryfield_data_type(self):
|
|
|
|
self.assertEqual(bytes(self.person_binary.data), b"binary data")
|
|
|
|
self.assertEqual(bytes(self.person_binary_get.data), b"binary data")
|
|
|
|
self.assertEqual(
|
|
|
|
type(self.person_binary_get.data),
|
|
|
|
type(self.__class__.person_binary_get.data),
|
|
|
|
)
|
|
|
|
self.assertEqual(
|
|
|
|
type(self.person_binary.data),
|
|
|
|
type(self.__class__.person_binary.data),
|
|
|
|
)
|
2018-11-24 10:22:09 +08:00
|
|
|
|
|
|
|
@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)
|
|
|
|
|
|
|
|
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.
|
|
|
|
"""
|
2022-02-04 03:24:19 +08:00
|
|
|
|
2018-11-24 10:22:09 +08:00
|
|
|
@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()
|