Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Added unit tests to fully check the performance of the serializer eng…

…ines.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@4719 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 7ccf9978adab5c0846b13f804f1bab25436e2564 1 parent 375c3ed
Russell Keith-Magee authored March 13, 2007
0  tests/regressiontests/serializers_regress/__init__.py
No changes.
170  tests/regressiontests/serializers_regress/models.py
... ...
@@ -0,0 +1,170 @@
  1
+"""
  2
+A test spanning all the capabilities of all the serializers.
  3
+
  4
+This class sets up a model for each model field type 
  5
+(except for image types, because of the PIL dependency).
  6
+"""
  7
+
  8
+from django.db import models
  9
+    
  10
+# The following classes are for testing basic data 
  11
+# marshalling, including NULL values.
  12
+
  13
+class BooleanData(models.Model):
  14
+    data = models.BooleanField(null=True)
  15
+    
  16
+class CharData(models.Model):
  17
+    data = models.CharField(maxlength=30, null=True)
  18
+
  19
+class DateData(models.Model):
  20
+    data = models.DateField(null=True)
  21
+
  22
+class DateTimeData(models.Model):
  23
+    data = models.DateTimeField(null=True)
  24
+
  25
+class EmailData(models.Model):
  26
+    data = models.EmailField(null=True)
  27
+
  28
+class FileData(models.Model):
  29
+    data = models.FileField(null=True, upload_to='/foo/bar')
  30
+
  31
+class FilePathData(models.Model):
  32
+    data = models.FilePathField(null=True)
  33
+
  34
+class FloatData(models.Model):
  35
+    data = models.FloatField(null=True, decimal_places=3, max_digits=5)
  36
+
  37
+class IntegerData(models.Model):
  38
+    data = models.IntegerField(null=True)
  39
+
  40
+# class ImageData(models.Model):
  41
+#    data = models.ImageField(null=True)
  42
+
  43
+class IPAddressData(models.Model):
  44
+    data = models.IPAddressField(null=True)
  45
+
  46
+class NullBooleanData(models.Model):
  47
+    data = models.NullBooleanField(null=True)
  48
+
  49
+class PhoneData(models.Model):
  50
+    data = models.PhoneNumberField(null=True)
  51
+
  52
+class PositiveIntegerData(models.Model):
  53
+    data = models.PositiveIntegerField(null=True)
  54
+
  55
+class PositiveSmallIntegerData(models.Model):
  56
+    data = models.PositiveSmallIntegerField(null=True)
  57
+
  58
+class SlugData(models.Model):
  59
+    data = models.SlugField(null=True)
  60
+
  61
+class SmallData(models.Model):
  62
+    data = models.SmallIntegerField(null=True)
  63
+
  64
+class TextData(models.Model):
  65
+    data = models.TextField(null=True)
  66
+
  67
+class TimeData(models.Model):
  68
+    data = models.TimeField(null=True)
  69
+
  70
+class USStateData(models.Model):
  71
+    data = models.USStateField(null=True)
  72
+
  73
+class XMLData(models.Model):
  74
+    data = models.XMLField(null=True)
  75
+    
  76
+# The following test classes are all for validation
  77
+# of related objects; in particular, forward, backward,
  78
+# and self references.
  79
+    
  80
+class Anchor(models.Model):
  81
+    """This is a model that can be used as 
  82
+    something for other models to point at"""
  83
+    
  84
+    data = models.CharField(maxlength=30)
  85
+    
  86
+class FKData(models.Model):
  87
+    data = models.ForeignKey(Anchor, null=True)
  88
+    
  89
+class M2MData(models.Model):
  90
+    data = models.ManyToManyField(Anchor, null=True)
  91
+    
  92
+class O2OData(models.Model):
  93
+    data = models.OneToOneField(Anchor, null=True)
  94
+
  95
+class FKSelfData(models.Model):
  96
+    data = models.ForeignKey('self', null=True)
  97
+    
  98
+class M2MSelfData(models.Model):
  99
+    data = models.ManyToManyField('self', null=True, symmetrical=False)
  100
+
  101
+# The following test classes are for validating the
  102
+# deserialization of objects that use a user-defined
  103
+# field as the primary key.
  104
+# Some of these data types have been commented out
  105
+# because they can't be used as a primary key on one
  106
+# or all database backends.
  107
+
  108
+class BooleanPKData(models.Model):
  109
+    data = models.BooleanField(primary_key=True)
  110
+    
  111
+class CharPKData(models.Model):
  112
+    data = models.CharField(maxlength=30, primary_key=True)
  113
+
  114
+# class DatePKData(models.Model):
  115
+#    data = models.DateField(primary_key=True)
  116
+
  117
+# class DateTimePKData(models.Model):
  118
+#    data = models.DateTimeField(primary_key=True)
  119
+
  120
+class EmailPKData(models.Model):
  121
+    data = models.EmailField(primary_key=True)
  122
+
  123
+class FilePKData(models.Model):
  124
+    data = models.FileField(primary_key=True, upload_to='/foo/bar')
  125
+
  126
+class FilePathPKData(models.Model):
  127
+    data = models.FilePathField(primary_key=True)
  128
+
  129
+class FloatPKData(models.Model):
  130
+    data = models.FloatField(primary_key=True, decimal_places=3, max_digits=5)
  131
+
  132
+class IntegerPKData(models.Model):
  133
+    data = models.IntegerField(primary_key=True)
  134
+
  135
+# class ImagePKData(models.Model):
  136
+#    data = models.ImageField(primary_key=True)
  137
+
  138
+class IPAddressPKData(models.Model):
  139
+    data = models.IPAddressField(primary_key=True)
  140
+
  141
+class NullBooleanPKData(models.Model):
  142
+    data = models.NullBooleanField(primary_key=True)
  143
+
  144
+class PhonePKData(models.Model):
  145
+    data = models.PhoneNumberField(primary_key=True)
  146
+
  147
+class PositiveIntegerPKData(models.Model):
  148
+    data = models.PositiveIntegerField(primary_key=True)
  149
+
  150
+class PositiveSmallIntegerPKData(models.Model):
  151
+    data = models.PositiveSmallIntegerField(primary_key=True)
  152
+
  153
+class SlugPKData(models.Model):
  154
+    data = models.SlugField(primary_key=True)
  155
+
  156
+class SmallPKData(models.Model):
  157
+    data = models.SmallIntegerField(primary_key=True)
  158
+
  159
+# class TextPKData(models.Model):
  160
+#     data = models.TextField(primary_key=True)
  161
+
  162
+# class TimePKData(models.Model):
  163
+#    data = models.TimeField(primary_key=True)
  164
+
  165
+class USStatePKData(models.Model):
  166
+    data = models.USStateField(primary_key=True)
  167
+
  168
+# class XMLPKData(models.Model):
  169
+#     data = models.XMLField(primary_key=True)
  170
+
243  tests/regressiontests/serializers_regress/tests.py
... ...
@@ -0,0 +1,243 @@
  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 fk_create(pk, klass, data):
  29
+    instance = klass(id=pk)
  30
+    setattr(instance, 'data_id', data)
  31
+    instance.save()
  32
+    return instance
  33
+    
  34
+def m2m_create(pk, klass, data):
  35
+    instance = klass(id=pk)
  36
+    instance.save()
  37
+    instance.data = data
  38
+    return instance
  39
+
  40
+def o2o_create(pk, klass, data):
  41
+    instance = klass()
  42
+    instance.data_id = data
  43
+    instance.save()
  44
+    return instance
  45
+
  46
+def pk_create(pk, klass, data):
  47
+    instance = klass()
  48
+    instance.data = data
  49
+    instance.save()
  50
+    return instance
  51
+
  52
+# A set of functions that can be used to compare
  53
+# test data objects of various kinds
  54
+def data_compare(testcase, pk, klass, data):
  55
+    instance = klass.objects.get(id=pk)
  56
+    testcase.assertEqual(data, instance.data, 
  57
+                         "Objects with PK=%d not equal; expected '%s', got '%s'" % (pk,data,instance.data))
  58
+
  59
+def fk_compare(testcase, pk, klass, data):
  60
+    instance = klass.objects.get(id=pk)
  61
+    testcase.assertEqual(data, instance.data_id)
  62
+
  63
+def m2m_compare(testcase, pk, klass, data):
  64
+    instance = klass.objects.get(id=pk)
  65
+    testcase.assertEqual(data, [obj.id for obj in instance.data.all()])
  66
+
  67
+def o2o_compare(testcase, pk, klass, data):
  68
+    instance = klass.objects.get(data=data)
  69
+    testcase.assertEqual(data, instance.data_id)
  70
+
  71
+def pk_compare(testcase, pk, klass, data):
  72
+    instance = klass.objects.get(data=data)
  73
+    testcase.assertEqual(data, instance.data)
  74
+        
  75
+# Define some data types. Each data type is
  76
+# actually a pair of functions; one to create
  77
+# and one to compare objects of that type
  78
+data_obj = (data_create, data_compare)
  79
+fk_obj = (fk_create, fk_compare)
  80
+m2m_obj = (m2m_create, m2m_compare)
  81
+o2o_obj = (o2o_create, o2o_compare)
  82
+pk_obj = (pk_create, pk_compare)
  83
+
  84
+test_data = [
  85
+    # Format: (data type, PK value, Model Class, data)  
  86
+    (data_obj, 1, BooleanData, True),
  87
+    (data_obj, 2, BooleanData, False),
  88
+    (data_obj, 10, CharData, "Test Char Data"),
  89
+    (data_obj, 11, CharData, ""),
  90
+    (data_obj, 12, CharData, "None"),
  91
+    (data_obj, 13, CharData, "null"),
  92
+    (data_obj, 14, CharData, "NULL"),
  93
+    (data_obj, 15, CharData, None),
  94
+    (data_obj, 20, DateData, datetime.date(2006,6,16)),
  95
+    (data_obj, 21, DateData, None),
  96
+    (data_obj, 30, DateTimeData, datetime.datetime(2006,6,16,10,42,37)),
  97
+    (data_obj, 31, DateTimeData, None),
  98
+    (data_obj, 40, EmailData, "hovercraft@example.com"),
  99
+    (data_obj, 41, EmailData, None),
  100
+    (data_obj, 50, FileData, 'file:///foo/bar/whiz.txt'),
  101
+    (data_obj, 51, FileData, None),
  102
+    (data_obj, 60, FilePathData, "/foo/bar/whiz.txt"),
  103
+    (data_obj, 61, FilePathData, None),
  104
+    (data_obj, 70, FloatData, 12.345),
  105
+    (data_obj, 71, FloatData, -12.345),
  106
+    (data_obj, 72, FloatData, 0.0),
  107
+    (data_obj, 73, FloatData, None),
  108
+    (data_obj, 80, IntegerData, 123456789),
  109
+    (data_obj, 81, IntegerData, -123456789),
  110
+    (data_obj, 82, IntegerData, 0),
  111
+    (data_obj, 83, IntegerData, None),
  112
+    #(XX, ImageData
  113
+    (data_obj, 90, IPAddressData, "127.0.0.1"),
  114
+    (data_obj, 91, IPAddressData, None),
  115
+    (data_obj, 100, NullBooleanData, True),
  116
+    (data_obj, 101, NullBooleanData, False),
  117
+    (data_obj, 102, NullBooleanData, None),
  118
+    (data_obj, 110, PhoneData, "212-634-5789"),
  119
+    (data_obj, 111, PhoneData, None),
  120
+    (data_obj, 120, PositiveIntegerData, 123456789),
  121
+    (data_obj, 121, PositiveIntegerData, None),
  122
+    (data_obj, 130, PositiveSmallIntegerData, 12),
  123
+    (data_obj, 131, PositiveSmallIntegerData, None),
  124
+    (data_obj, 140, SlugData, "this-is-a-slug"),
  125
+    (data_obj, 141, SlugData, None),
  126
+    (data_obj, 150, SmallData, 12), 
  127
+    (data_obj, 151, SmallData, -12), 
  128
+    (data_obj, 152, SmallData, 0), 
  129
+    (data_obj, 153, SmallData, None), 
  130
+    (data_obj, 160, TextData, """This is a long piece of text.
  131
+It contains line breaks.
  132
+Several of them.
  133
+The end."""),
  134
+    (data_obj, 161, TextData, ""),
  135
+    (data_obj, 162, TextData, None),
  136
+    (data_obj, 170, TimeData, datetime.time(10,42,37)),
  137
+    (data_obj, 171, TimeData, None),
  138
+    (data_obj, 180, USStateData, "MA"),
  139
+    (data_obj, 181, USStateData, None),
  140
+    (data_obj, 190, XMLData, "<foo></foo>"),
  141
+    (data_obj, 191, XMLData, None),
  142
+
  143
+    (data_obj, 300, Anchor, "Anchor 1"),
  144
+    (data_obj, 301, Anchor, "Anchor 2"),
  145
+
  146
+    (fk_obj, 400, FKData, 300), # Post reference
  147
+    (fk_obj, 401, FKData, 500), # Pre reference
  148
+    (fk_obj, 402, FKData, None), # Empty reference
  149
+
  150
+    (m2m_obj, 410, M2MData, []), # Empty set
  151
+    (m2m_obj, 411, M2MData, [300,301]), # Post reference
  152
+    (m2m_obj, 412, M2MData, [500,501]), # Pre reference
  153
+    (m2m_obj, 413, M2MData, [300,301,500,501]), # Pre and Post reference
  154
+
  155
+    (o2o_obj, None, O2OData, 300), # Post reference
  156
+    (o2o_obj, None, O2OData, 500), # Pre reference
  157
+
  158
+    (fk_obj, 430, FKSelfData, 431), # Pre reference
  159
+    (fk_obj, 431, FKSelfData, 430), # Post reference
  160
+    (fk_obj, 432, FKSelfData, None), # Empty reference
  161
+
  162
+    (m2m_obj, 440, M2MSelfData, []),
  163
+    (m2m_obj, 441, M2MSelfData, []),
  164
+    (m2m_obj, 442, M2MSelfData, [440, 441]),
  165
+    (m2m_obj, 443, M2MSelfData, [445, 446]),
  166
+    (m2m_obj, 444, M2MSelfData, [440, 441, 445, 446]),
  167
+    (m2m_obj, 445, M2MSelfData, []),
  168
+    (m2m_obj, 446, M2MSelfData, []),
  169
+
  170
+    (data_obj, 500, Anchor, "Anchor 3"),
  171
+    (data_obj, 501, Anchor, "Anchor 4"),
  172
+
  173
+    (pk_obj, 601, BooleanPKData, True),
  174
+    (pk_obj, 602, BooleanPKData, False),
  175
+    (pk_obj, 610, CharPKData, "Test Char PKData"),
  176
+#     (pk_obj, 620, DatePKData, datetime.date(2006,6,16)),
  177
+#     (pk_obj, 630, DateTimePKData, datetime.datetime(2006,6,16,10,42,37)),
  178
+    (pk_obj, 640, EmailPKData, "hovercraft@example.com"),
  179
+    (pk_obj, 650, FilePKData, 'file:///foo/bar/whiz.txt'),
  180
+    (pk_obj, 660, FilePathPKData, "/foo/bar/whiz.txt"),
  181
+    (pk_obj, 670, FloatPKData, 12.345),
  182
+    (pk_obj, 671, FloatPKData, -12.345),
  183
+    (pk_obj, 672, FloatPKData, 0.0),
  184
+    (pk_obj, 680, IntegerPKData, 123456789),
  185
+    (pk_obj, 681, IntegerPKData, -123456789),
  186
+    (pk_obj, 682, IntegerPKData, 0),
  187
+#     (XX, ImagePKData
  188
+    (pk_obj, 690, IPAddressPKData, "127.0.0.1"),
  189
+    (pk_obj, 700, NullBooleanPKData, True),
  190
+    (pk_obj, 701, NullBooleanPKData, False),
  191
+    (pk_obj, 710, PhonePKData, "212-634-5789"),
  192
+    (pk_obj, 720, PositiveIntegerPKData, 123456789),
  193
+    (pk_obj, 730, PositiveSmallIntegerPKData, 12),
  194
+    (pk_obj, 740, SlugPKData, "this-is-a-slug"),
  195
+    (pk_obj, 750, SmallPKData, 12), 
  196
+    (pk_obj, 751, SmallPKData, -12), 
  197
+    (pk_obj, 752, SmallPKData, 0), 
  198
+#     (pk_obj, 760, TextPKData, """This is a long piece of text.
  199
+# It contains line breaks.
  200
+# Several of them.
  201
+# The end."""),
  202
+#    (pk_obj, 770, TimePKData, datetime.time(10,42,37)),
  203
+    (pk_obj, 780, USStatePKData, "MA"),
  204
+#     (pk_obj, 790, XMLPKData, "<foo></foo>"),
  205
+]
  206
+    
  207
+# Dynamically create serializer tests to ensure that all
  208
+# registered serializers are automatically tested.
  209
+class SerializerTests(unittest.TestCase):
  210
+    pass
  211
+
  212
+def serializerTest(format, self):
  213
+    # Clear the database first
  214
+    management.flush(verbosity=0, interactive=False)    
  215
+
  216
+    # Create all the objects defined in the test data
  217
+    objects = []
  218
+    transaction.enter_transaction_management()
  219
+    transaction.managed(True)
  220
+    for (func, pk, klass, datum) in test_data:
  221
+        objects.append(func[0](pk, klass, datum))
  222
+    transaction.commit()
  223
+    transaction.leave_transaction_management()
  224
+
  225
+    # Serialize the test database
  226
+    serialized_data = serializers.serialize(format, objects, indent=2)
  227
+
  228
+    # Flush the database and recreate from the serialized data
  229
+    management.flush(verbosity=0, interactive=False)    
  230
+    transaction.enter_transaction_management()
  231
+    transaction.managed(True)
  232
+    for obj in serializers.deserialize(format, serialized_data):
  233
+        obj.save()
  234
+    transaction.commit()
  235
+    transaction.leave_transaction_management()
  236
+
  237
+    # Assert that the deserialized data is the same 
  238
+    # as the original source
  239
+    for (func, pk, klass, datum) in test_data:
  240
+        func[1](self, pk, klass, datum)
  241
+    
  242
+for format in serializers.get_serializer_formats():
  243
+    setattr(SerializerTests, 'test_'+format+'_serializer', curry(serializerTest, format))

0 notes on commit 7ccf997

Please sign in to comment.
Something went wrong with that request. Please try again.