Added a basic benchmark suite for serializers.

This commit is contained in:
Omer Katz 2015-02-03 10:00:42 +02:00
parent 6e2ea852d0
commit 59659835e8
7 changed files with 185 additions and 38 deletions

View File

@ -5,6 +5,7 @@ Django>=1.4.11
pytest-django==2.8.0
pytest==2.6.4
pytest-cov==1.6
pytest-bench==0.3.0
flake8==2.2.2
# Optional packages

View File

@ -8,8 +8,8 @@ import subprocess
PYTEST_ARGS = {
'default': ['tests', '--tb=short'],
'fast': ['tests', '--tb=short', '-q'],
'default': ['tests', '--tb=short', '--bench'],
'fast': ['tests', '--tb=short', '-q', '--bench'],
}
FLAKE8_ARGS = ['rest_framework', 'tests', '--ignore=E501']

10
tests/fields.py Normal file
View File

@ -0,0 +1,10 @@
#!/usr/bin/env python
# coding: utf-8
from django.db import models
class CustomField(models.Field):
"""
A custom model field simply for testing purposes.
"""
pass

View File

@ -1,6 +1,7 @@
from __future__ import unicode_literals
from django.db import models
from django.utils.translation import ugettext_lazy as _
from .fields import CustomField
class RESTFrameworkModel(models.Model):
@ -68,3 +69,62 @@ class NullableOneToOneSource(RESTFrameworkModel):
name = models.CharField(max_length=100)
target = models.OneToOneField(OneToOneTarget, null=True, blank=True,
related_name='nullable_source')
class RegularFieldsModel(models.Model):
"""
A model class for testing regular flat fields.
"""
auto_field = models.AutoField(primary_key=True)
big_integer_field = models.BigIntegerField()
boolean_field = models.BooleanField(default=False)
char_field = models.CharField(max_length=100)
comma_separated_integer_field = models.CommaSeparatedIntegerField(max_length=100)
date_field = models.DateField()
datetime_field = models.DateTimeField()
decimal_field = models.DecimalField(max_digits=3, decimal_places=1)
email_field = models.EmailField(max_length=100)
float_field = models.FloatField()
integer_field = models.IntegerField()
null_boolean_field = models.NullBooleanField()
positive_integer_field = models.PositiveIntegerField()
positive_small_integer_field = models.PositiveSmallIntegerField()
slug_field = models.SlugField(max_length=100)
small_integer_field = models.SmallIntegerField()
text_field = models.TextField()
time_field = models.TimeField()
url_field = models.URLField(max_length=100)
custom_field = CustomField()
def method(self):
return 'method'
class RegularFieldsAndFKModel(models.Model):
"""
A model class for testing regular flat fields.
"""
auto_field = models.AutoField(primary_key=True)
big_integer_field = models.BigIntegerField()
boolean_field = models.BooleanField(default=False)
char_field = models.CharField(max_length=100)
comma_separated_integer_field = models.CommaSeparatedIntegerField(max_length=100)
date_field = models.DateField()
datetime_field = models.DateTimeField()
decimal_field = models.DecimalField(max_digits=3, decimal_places=1)
email_field = models.EmailField(max_length=100)
float_field = models.FloatField()
integer_field = models.IntegerField()
null_boolean_field = models.NullBooleanField()
positive_integer_field = models.PositiveIntegerField()
positive_small_integer_field = models.PositiveSmallIntegerField()
slug_field = models.SlugField(max_length=100)
small_integer_field = models.SmallIntegerField()
text_field = models.TextField()
time_field = models.TimeField()
url_field = models.URLField(max_length=100)
custom_field = CustomField()
fk = models.ForeignKey(RegularFieldsModel)
def method(self):
return 'method'

View File

@ -6,13 +6,16 @@ These tests deal with ensuring that we correctly map the model fields onto
an appropriate set of serializer fields for each case.
"""
from __future__ import unicode_literals
from django.core.exceptions import ImproperlyConfigured
from django.core.validators import MaxValueValidator, MinValueValidator, MinLengthValidator
from django.db import models
from django.test import TestCase
from django.utils import six
from rest_framework import serializers
from rest_framework.compat import unicode_repr
from .models import RegularFieldsModel
def dedent(blocktext):
@ -22,46 +25,11 @@ def dedent(blocktext):
# Tests for regular field mappings.
# ---------------------------------
class CustomField(models.Field):
"""
A custom model field simply for testing purposes.
"""
pass
class OneFieldModel(models.Model):
char_field = models.CharField(max_length=100)
class RegularFieldsModel(models.Model):
"""
A model class for testing regular flat fields.
"""
auto_field = models.AutoField(primary_key=True)
big_integer_field = models.BigIntegerField()
boolean_field = models.BooleanField(default=False)
char_field = models.CharField(max_length=100)
comma_separated_integer_field = models.CommaSeparatedIntegerField(max_length=100)
date_field = models.DateField()
datetime_field = models.DateTimeField()
decimal_field = models.DecimalField(max_digits=3, decimal_places=1)
email_field = models.EmailField(max_length=100)
float_field = models.FloatField()
integer_field = models.IntegerField()
null_boolean_field = models.NullBooleanField()
positive_integer_field = models.PositiveIntegerField()
positive_small_integer_field = models.PositiveSmallIntegerField()
slug_field = models.SlugField(max_length=100)
small_integer_field = models.SmallIntegerField()
text_field = models.TextField()
time_field = models.TimeField()
url_field = models.URLField(max_length=100)
custom_field = CustomField()
def method(self):
return 'method'
COLOR_CHOICES = (('red', 'Red'), ('blue', 'Blue'), ('green', 'Green'))
@ -125,7 +93,7 @@ class TestRegularFieldMappings(TestCase):
text_field = CharField(style={'base_template': 'textarea.html'})
time_field = TimeField()
url_field = URLField(max_length=100)
custom_field = ModelField(model_field=<tests.test_model_serializer.CustomField: custom_field>)
custom_field = ModelField(model_field=<tests.fields.CustomField: custom_field>)
""")
self.assertEqual(unicode_repr(TestSerializer()), expected)

View File

@ -0,0 +1,107 @@
from decimal import Decimal
from pytest import mark
from datetime import datetime
from rest_framework import serializers
from .models import RegularFieldsModel, RegularFieldsAndFKModel
data = {
'big_integer_field': 100000,
'char_field': 'a',
'comma_separated_integer_field': '1,2',
'date_field': datetime.now().date(),
'datetime_field': datetime.now(),
'decimal_field': Decimal('1.5'),
'email_field': 'somewhere@overtherainbow.com',
'float_field': 0.443,
'integer_field': 55,
'null_boolean_field': True,
'positive_integer_field': 1,
'positive_small_integer_field': 1,
'slug_field': 'slug-friendly-text',
'small_integer_field': 1,
'text_field': 'lorem ipsum',
'time_field': datetime.now().time(),
'url_field': 'https://overtherainbow.com'
}
class TestSerializer(serializers.ModelSerializer):
class Meta:
model = RegularFieldsModel
fields = data.keys() + ['method']
class TestNestedSerializer(serializers.ModelSerializer):
fk = TestSerializer()
class Meta:
model = RegularFieldsAndFKModel
fields = data.keys() + ['method', 'fk']
@mark.bench('serializers.ModelSerializer.to_representation')
def test_object_serialization():
instance = RegularFieldsModel(**data)
serializer = TestSerializer(instance=instance)
assert serializer.data, serializer.errors
@mark.bench('serializers.ModelSerializer.to_representation')
def test_nested_object_serialization():
nested_instance = RegularFieldsModel(**data)
instance = RegularFieldsAndFKModel(fk=nested_instance, **data)
serializer = TestSerializer(instance=instance)
assert serializer.data, serializer.errors
@mark.bench('serializers.ModelSerializer.to_representation')
def test_object_list_serialization():
instance = [RegularFieldsModel(**data) for _ in range(100)]
serializer = TestSerializer(instance=instance, many=True)
assert serializer.data, serializer.errors
@mark.bench('serializers.ModelSerializer.to_representation')
def test_object_serialization_with_partial_update():
instance = RegularFieldsModel(**data)
serializer = TestSerializer(instance=instance, data={'char_field': 'b'}, partial=True)
assert serializer.is_valid(), serializer.errors
assert serializer.data, serializer.errors
@mark.bench('serializers.ModelSerializer.to_representation')
def test_object_serialization_with_update():
instance = RegularFieldsModel(**data)
new_data = data.copy()
new_data['char_field'] = 'b'
serializer = TestSerializer(instance=instance, data=new_data)
assert serializer.is_valid(), serializer.errors
assert serializer.data, serializer.errors
@mark.bench('serializers.ModelSerializer.to_internal_value')
def test_object_deserialization():
serializer = TestSerializer(data=data)
assert serializer.is_valid(), serializer.errors
@mark.bench('serializers.ModelSerializer.to_internal_value')
def test_object_list_deserialization():
serializer = TestSerializer(data=[data for _ in range(100)], many=True)
assert serializer.is_valid(), serializer.errors
@mark.bench('serializers.ModelSerializer.__init__')
def test_serializer_initialization():
TestSerializer(data=data)

View File

@ -22,6 +22,7 @@ deps =
{py26,py27}-django{14,15}: django-oauth2-provider==0.2.3
{py26,py27}-django16: django-oauth2-provider==0.2.4
pytest-django==2.8.0
pytest-bench==0.3.0
django-filter==0.9.2
defusedxml==0.3
markdown>=2.1.0