1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
|
import pickle
from functools import wraps
from django.db import IntegrityError, connections, transaction
from django.test import TestCase, skipUnlessDBFeature
from django.test.testcases import (
DatabaseOperationForbidden,
SimpleTestCase,
TestData,
is_pickable,
)
from .models import Car, Person, PossessedCar
class UnpicklableObject:
def __getstate__(self):
raise pickle.PickleError("cannot be pickled for testing reasons")
class TestSimpleTestCase(SimpleTestCase):
def test_is_picklable_with_non_picklable_properties(self):
"""ParallelTestSuite requires that all TestCases are picklable."""
self.non_picklable = lambda: 0
self.assertEqual(self, pickle.loads(pickle.dumps(self)))
def test_is_picklable_with_non_picklable_object(self):
unpicklable_obj = UnpicklableObject()
self.assertEqual(is_pickable(unpicklable_obj), False)
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
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."
)
with self.assertRaisesMessage(DatabaseOperationForbidden, message):
connections["other"].connect()
with self.assertRaisesMessage(DatabaseOperationForbidden, message):
connections["other"].temporary_connection()
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."
)
with self.assertRaisesMessage(DatabaseOperationForbidden, message):
Car.objects.using("other").get()
@skipUnlessDBFeature("supports_transactions")
def test_reset_sequences(self):
old_reset_sequences = self.__class__.reset_sequences
self.__class__.reset_sequences = True
self.addCleanup(setattr, self.__class__, "reset_sequences", old_reset_sequences)
msg = "reset_sequences cannot be used on TestCase instances"
with self.assertRaisesMessage(TypeError, msg):
self._fixture_setup()
def assert_no_queries(test):
@wraps(test)
def inner(self):
with self.assertNumQueries(0):
test(self)
return inner
# 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")
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.person_binary = Person.objects.create(name="Person", data=b"binary data")
cls.person_binary_get = Person.objects.get(pk=cls.person_binary.pk)
@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)
self.assertEqual(self.person_binary, self.__class__.person_binary)
self.assertEqual(self.person_binary_get, self.__class__.person_binary_get)
@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)
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),
)
@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.
"""
@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()
|