1 """ |
|
2 A test spanning all the capabilities of all the serializers. |
|
3 |
|
4 This class defines sample data and a dynamically generated |
|
5 test case that is capable of testing the capabilities of |
|
6 the serializers. This includes all valid data values, plus |
|
7 forward, backwards and self references. |
|
8 """ |
|
9 |
|
10 |
|
11 import unittest, datetime |
|
12 |
|
13 from django.utils.functional import curry |
|
14 from django.core import serializers |
|
15 from django.db import transaction |
|
16 from django.core import management |
|
17 |
|
18 from models import * |
|
19 |
|
20 # A set of functions that can be used to recreate |
|
21 # test data objects of various kinds |
|
22 def data_create(pk, klass, data): |
|
23 instance = klass(id=pk) |
|
24 instance.data = data |
|
25 instance.save() |
|
26 return instance |
|
27 |
|
28 def generic_create(pk, klass, data): |
|
29 instance = klass(id=pk) |
|
30 instance.data = data[0] |
|
31 instance.save() |
|
32 for tag in data[1:]: |
|
33 instance.tags.create(data=tag) |
|
34 return instance |
|
35 |
|
36 def fk_create(pk, klass, data): |
|
37 instance = klass(id=pk) |
|
38 setattr(instance, 'data_id', data) |
|
39 instance.save() |
|
40 return instance |
|
41 |
|
42 def m2m_create(pk, klass, data): |
|
43 instance = klass(id=pk) |
|
44 instance.save() |
|
45 instance.data = data |
|
46 return instance |
|
47 |
|
48 def o2o_create(pk, klass, data): |
|
49 instance = klass() |
|
50 instance.data_id = data |
|
51 instance.save() |
|
52 return instance |
|
53 |
|
54 def pk_create(pk, klass, data): |
|
55 instance = klass() |
|
56 instance.data = data |
|
57 instance.save() |
|
58 return instance |
|
59 |
|
60 # A set of functions that can be used to compare |
|
61 # test data objects of various kinds |
|
62 def data_compare(testcase, pk, klass, data): |
|
63 instance = klass.objects.get(id=pk) |
|
64 testcase.assertEqual(data, instance.data, |
|
65 "Objects with PK=%d not equal; expected '%s' (%s), got '%s' (%s)" % (pk,data, type(data), instance.data, type(instance.data))) |
|
66 |
|
67 def generic_compare(testcase, pk, klass, data): |
|
68 instance = klass.objects.get(id=pk) |
|
69 testcase.assertEqual(data[0], instance.data) |
|
70 testcase.assertEqual(data[1:], [t.data for t in instance.tags.all()]) |
|
71 |
|
72 def fk_compare(testcase, pk, klass, data): |
|
73 instance = klass.objects.get(id=pk) |
|
74 testcase.assertEqual(data, instance.data_id) |
|
75 |
|
76 def m2m_compare(testcase, pk, klass, data): |
|
77 instance = klass.objects.get(id=pk) |
|
78 testcase.assertEqual(data, [obj.id for obj in instance.data.all()]) |
|
79 |
|
80 def o2o_compare(testcase, pk, klass, data): |
|
81 instance = klass.objects.get(data=data) |
|
82 testcase.assertEqual(data, instance.data_id) |
|
83 |
|
84 def pk_compare(testcase, pk, klass, data): |
|
85 instance = klass.objects.get(data=data) |
|
86 testcase.assertEqual(data, instance.data) |
|
87 |
|
88 # Define some data types. Each data type is |
|
89 # actually a pair of functions; one to create |
|
90 # and one to compare objects of that type |
|
91 data_obj = (data_create, data_compare) |
|
92 generic_obj = (generic_create, generic_compare) |
|
93 fk_obj = (fk_create, fk_compare) |
|
94 m2m_obj = (m2m_create, m2m_compare) |
|
95 o2o_obj = (o2o_create, o2o_compare) |
|
96 pk_obj = (pk_create, pk_compare) |
|
97 |
|
98 test_data = [ |
|
99 # Format: (data type, PK value, Model Class, data) |
|
100 (data_obj, 1, BooleanData, True), |
|
101 (data_obj, 2, BooleanData, False), |
|
102 (data_obj, 10, CharData, "Test Char Data"), |
|
103 (data_obj, 11, CharData, ""), |
|
104 (data_obj, 12, CharData, "None"), |
|
105 (data_obj, 13, CharData, "null"), |
|
106 (data_obj, 14, CharData, "NULL"), |
|
107 (data_obj, 15, CharData, None), |
|
108 (data_obj, 20, DateData, datetime.date(2006,6,16)), |
|
109 (data_obj, 21, DateData, None), |
|
110 (data_obj, 30, DateTimeData, datetime.datetime(2006,6,16,10,42,37)), |
|
111 (data_obj, 31, DateTimeData, None), |
|
112 (data_obj, 40, EmailData, "hovercraft@example.com"), |
|
113 (data_obj, 41, EmailData, None), |
|
114 (data_obj, 50, FileData, 'file:///foo/bar/whiz.txt'), |
|
115 (data_obj, 51, FileData, None), |
|
116 (data_obj, 60, FilePathData, "/foo/bar/whiz.txt"), |
|
117 (data_obj, 61, FilePathData, None), |
|
118 (data_obj, 70, FloatData, 12.345), |
|
119 (data_obj, 71, FloatData, -12.345), |
|
120 (data_obj, 72, FloatData, 0.0), |
|
121 (data_obj, 73, FloatData, None), |
|
122 (data_obj, 80, IntegerData, 123456789), |
|
123 (data_obj, 81, IntegerData, -123456789), |
|
124 (data_obj, 82, IntegerData, 0), |
|
125 (data_obj, 83, IntegerData, None), |
|
126 #(XX, ImageData |
|
127 (data_obj, 90, IPAddressData, "127.0.0.1"), |
|
128 (data_obj, 91, IPAddressData, None), |
|
129 (data_obj, 100, NullBooleanData, True), |
|
130 (data_obj, 101, NullBooleanData, False), |
|
131 (data_obj, 102, NullBooleanData, None), |
|
132 (data_obj, 110, PhoneData, "212-634-5789"), |
|
133 (data_obj, 111, PhoneData, None), |
|
134 (data_obj, 120, PositiveIntegerData, 123456789), |
|
135 (data_obj, 121, PositiveIntegerData, None), |
|
136 (data_obj, 130, PositiveSmallIntegerData, 12), |
|
137 (data_obj, 131, PositiveSmallIntegerData, None), |
|
138 (data_obj, 140, SlugData, "this-is-a-slug"), |
|
139 (data_obj, 141, SlugData, None), |
|
140 (data_obj, 150, SmallData, 12), |
|
141 (data_obj, 151, SmallData, -12), |
|
142 (data_obj, 152, SmallData, 0), |
|
143 (data_obj, 153, SmallData, None), |
|
144 (data_obj, 160, TextData, """This is a long piece of text. |
|
145 It contains line breaks. |
|
146 Several of them. |
|
147 The end."""), |
|
148 (data_obj, 161, TextData, ""), |
|
149 (data_obj, 162, TextData, None), |
|
150 (data_obj, 170, TimeData, datetime.time(10,42,37)), |
|
151 (data_obj, 171, TimeData, None), |
|
152 (data_obj, 180, USStateData, "MA"), |
|
153 (data_obj, 181, USStateData, None), |
|
154 (data_obj, 190, XMLData, "<foo></foo>"), |
|
155 (data_obj, 191, XMLData, None), |
|
156 |
|
157 (generic_obj, 200, GenericData, ['Generic Object 1', 'tag1', 'tag2']), |
|
158 (generic_obj, 201, GenericData, ['Generic Object 2', 'tag2', 'tag3']), |
|
159 |
|
160 (data_obj, 300, Anchor, "Anchor 1"), |
|
161 (data_obj, 301, Anchor, "Anchor 2"), |
|
162 |
|
163 (fk_obj, 400, FKData, 300), # Post reference |
|
164 (fk_obj, 401, FKData, 500), # Pre reference |
|
165 (fk_obj, 402, FKData, None), # Empty reference |
|
166 |
|
167 (m2m_obj, 410, M2MData, []), # Empty set |
|
168 (m2m_obj, 411, M2MData, [300,301]), # Post reference |
|
169 (m2m_obj, 412, M2MData, [500,501]), # Pre reference |
|
170 (m2m_obj, 413, M2MData, [300,301,500,501]), # Pre and Post reference |
|
171 |
|
172 (o2o_obj, None, O2OData, 300), # Post reference |
|
173 (o2o_obj, None, O2OData, 500), # Pre reference |
|
174 |
|
175 (fk_obj, 430, FKSelfData, 431), # Pre reference |
|
176 (fk_obj, 431, FKSelfData, 430), # Post reference |
|
177 (fk_obj, 432, FKSelfData, None), # Empty reference |
|
178 |
|
179 (m2m_obj, 440, M2MSelfData, []), |
|
180 (m2m_obj, 441, M2MSelfData, []), |
|
181 (m2m_obj, 442, M2MSelfData, [440, 441]), |
|
182 (m2m_obj, 443, M2MSelfData, [445, 446]), |
|
183 (m2m_obj, 444, M2MSelfData, [440, 441, 445, 446]), |
|
184 (m2m_obj, 445, M2MSelfData, []), |
|
185 (m2m_obj, 446, M2MSelfData, []), |
|
186 |
|
187 (data_obj, 500, Anchor, "Anchor 3"), |
|
188 (data_obj, 501, Anchor, "Anchor 4"), |
|
189 |
|
190 (pk_obj, 601, BooleanPKData, True), |
|
191 (pk_obj, 602, BooleanPKData, False), |
|
192 (pk_obj, 610, CharPKData, "Test Char PKData"), |
|
193 # (pk_obj, 620, DatePKData, datetime.date(2006,6,16)), |
|
194 # (pk_obj, 630, DateTimePKData, datetime.datetime(2006,6,16,10,42,37)), |
|
195 (pk_obj, 640, EmailPKData, "hovercraft@example.com"), |
|
196 (pk_obj, 650, FilePKData, 'file:///foo/bar/whiz.txt'), |
|
197 (pk_obj, 660, FilePathPKData, "/foo/bar/whiz.txt"), |
|
198 (pk_obj, 670, FloatPKData, 12.345), |
|
199 (pk_obj, 671, FloatPKData, -12.345), |
|
200 (pk_obj, 672, FloatPKData, 0.0), |
|
201 (pk_obj, 680, IntegerPKData, 123456789), |
|
202 (pk_obj, 681, IntegerPKData, -123456789), |
|
203 (pk_obj, 682, IntegerPKData, 0), |
|
204 # (XX, ImagePKData |
|
205 (pk_obj, 690, IPAddressPKData, "127.0.0.1"), |
|
206 (pk_obj, 700, NullBooleanPKData, True), |
|
207 (pk_obj, 701, NullBooleanPKData, False), |
|
208 (pk_obj, 710, PhonePKData, "212-634-5789"), |
|
209 (pk_obj, 720, PositiveIntegerPKData, 123456789), |
|
210 (pk_obj, 730, PositiveSmallIntegerPKData, 12), |
|
211 (pk_obj, 740, SlugPKData, "this-is-a-slug"), |
|
212 (pk_obj, 750, SmallPKData, 12), |
|
213 (pk_obj, 751, SmallPKData, -12), |
|
214 (pk_obj, 752, SmallPKData, 0), |
|
215 # (pk_obj, 760, TextPKData, """This is a long piece of text. |
|
216 # It contains line breaks. |
|
217 # Several of them. |
|
218 # The end."""), |
|
219 # (pk_obj, 770, TimePKData, datetime.time(10,42,37)), |
|
220 (pk_obj, 780, USStatePKData, "MA"), |
|
221 # (pk_obj, 790, XMLPKData, "<foo></foo>"), |
|
222 ] |
|
223 |
|
224 # Dynamically create serializer tests to ensure that all |
|
225 # registered serializers are automatically tested. |
|
226 class SerializerTests(unittest.TestCase): |
|
227 pass |
|
228 |
|
229 def serializerTest(format, self): |
|
230 # Clear the database first |
|
231 management.flush(verbosity=0, interactive=False) |
|
232 |
|
233 # Create all the objects defined in the test data |
|
234 objects = [] |
|
235 transaction.enter_transaction_management() |
|
236 transaction.managed(True) |
|
237 for (func, pk, klass, datum) in test_data: |
|
238 objects.append(func[0](pk, klass, datum)) |
|
239 transaction.commit() |
|
240 transaction.leave_transaction_management() |
|
241 |
|
242 # Add the generic tagged objects to the object list |
|
243 objects.extend(Tag.objects.all()) |
|
244 |
|
245 # Serialize the test database |
|
246 serialized_data = serializers.serialize(format, objects, indent=2) |
|
247 |
|
248 # Flush the database and recreate from the serialized data |
|
249 management.flush(verbosity=0, interactive=False) |
|
250 transaction.enter_transaction_management() |
|
251 transaction.managed(True) |
|
252 for obj in serializers.deserialize(format, serialized_data): |
|
253 obj.save() |
|
254 transaction.commit() |
|
255 transaction.leave_transaction_management() |
|
256 |
|
257 # Assert that the deserialized data is the same |
|
258 # as the original source |
|
259 for (func, pk, klass, datum) in test_data: |
|
260 func[1](self, pk, klass, datum) |
|
261 |
|
262 for format in serializers.get_serializer_formats(): |
|
263 setattr(SerializerTests, 'test_'+format+'_serializer', curry(serializerTest, format)) |
|