Skip to content

Commit

Permalink
Fixed few bugs in the order of random generators. Integerated random …
Browse files Browse the repository at this point in the history
…value generation to djenerator. Added tests to all random generators with coverage update.
  • Loading branch information
mostafa-mahmoud committed Nov 4, 2016
1 parent 77de123 commit d4701ba
Show file tree
Hide file tree
Showing 6 changed files with 187 additions and 46 deletions.
11 changes: 6 additions & 5 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,20 @@ At this stage a very simple modification needs to be done to the model descripti
Name Stmts Miss Cover Missing
--------------------------------------------------------------
djenerator/__init__ 0 0 100%
djenerator/generate_test_data 166 1 99% 39
djenerator/fields_generator 90 5 94% 91, 93, 95, 97, 99
djenerator/generate_test_data 170 1 99% 41
djenerator/management/__init__ 0 0 100%
djenerator/model_reader 46 0 100%
djenerator/models 0 0 100%
djenerator/utility 44 0 100%
djenerator/values_generator 130 1 99% 180
djenerator/values_generator 131 0 100%
example/__init__ 0 0 100%
example/admin 1 0 100%
example/models 62 11 82% 11, 28, 32-43, 47, 75, 86, 90, 108
runtests 28 2 93% 72-73
tests/__init__ 0 0 100%
tests/admin 1 0 100%
tests/models 188 7 96% 48, 59, 70, 85, 98, 108, 121
tests/tests 519 2 99% 90, 383
tests/models 207 7 97% 48, 59, 70, 85, 98, 108, 121
tests/tests 608 2 99% 179, 472
--------------------------------------------------------------
TOTAL 1185 24 98%
TOTAL 1388 28 98%
21 changes: 14 additions & 7 deletions djenerator/fields_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from django.db.models.fields import DateField
from django.db.models.fields import DateTimeField
from django.db.models.fields import DecimalField
from django.db.models.fields import DurationField
from django.db.models.fields import EmailField
from django.db.models.fields import FilePathField
from django.db.models.fields import FloatField
Expand All @@ -25,7 +26,6 @@
from django.db.models.fields import TimeField
from django.db.models.fields import URLField
from django.db.models.fields import UUIDField

from values_generator import generate_big_integer
from values_generator import generate_boolean
from values_generator import generate_comma_separated_int
Expand All @@ -48,22 +48,18 @@ def generate_values(field, size=100):
def generate_value(field):
if isinstance(field, BigIntegerField):
return generate_big_integer()
elif isinstance(field, IntegerField):
return generate_int()
elif isinstance(field, EmailField):
return generate_email(field.max_length)
elif isinstance(field, BooleanField):
return generate_boolean(field.null)
elif isinstance(field, CharField):
return generate_string(field.max_length)
elif isinstance(field, CommaSeparatedIntegerField):
return generate_comma_separated_int(field.max_length)
elif isinstance(field, DecimalField):
return generate_decimal(32, 8)
elif isinstance(field, DateField):
return generate_date_time().date()
elif isinstance(field, DateTimeField):
return generate_date_time()
elif isinstance(field, DateField):
return generate_date_time().date()
elif isinstance(field, FloatField):
return generate_float()
elif isinstance(field, NullBooleanField):
Expand All @@ -78,8 +74,19 @@ def generate_value(field):
return generate_small_integer()
elif isinstance(field, TimeField):
return generate_date_time().time()
elif isinstance(field, IntegerField):
return generate_int()
elif isinstance(field, GenericIPAddressField):
return generate_ip()
elif isinstance(field, DurationField):
t1 = generate_date_time()
t2 = generate_date_time()
if t1 < t2:
return t2 - t1
else:
return t1 - t2
elif isinstance(field, CharField):
return generate_string(field.max_length)
elif isinstance(field, BinaryField):
pass
elif isinstance(field, URLField):
Expand Down
15 changes: 9 additions & 6 deletions djenerator/generate_test_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
given models.
"""
import inspect
import os
import random
from django.core import management
from django.core import serializers
from django.db import connection
from django.db.models import Model
from fields_generator import generate_values
from model_reader import is_auto_field
from model_reader import is_related
from model_reader import is_required
Expand Down Expand Up @@ -41,8 +43,8 @@ def field_sample_values(field):
model = field.rel.to
list_field_values = list(model.objects.all())
if 'ManyToMany' in relation_type(field) and list_field_values:
sz = random.randint(1, len(list_field_values))
list_field_values = [random.sample(list_field_values, sz)]
siz = random.randint(1, len(list_field_values))
list_field_values = [random.sample(list_field_values, siz)]
else:
found = False
if hasattr(field.model, 'TestData'):
Expand All @@ -68,10 +70,11 @@ def field_sample_values(field):
app_name = field.model._meta.app_label
path = '%s/TestTemplates/sample__%s__%s' % (app_name,
field.model.__name__, field.name)
input_file = open(path, 'r')
list_field_values = [word[:-1] for word in input_file]
# TODO(mostafa-mahmoud) : Generate totally randomized
# objects if the file is not found.
if os.path.exists(path):
input_file = open(path, 'r')
list_field_values = [word[:-1] for word in input_file]
else:
list_field_values = generate_values(field)
return list(list_field_values)


Expand Down
5 changes: 3 additions & 2 deletions djenerator/values_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,10 @@ def generate_ip():

def generate_comma_separated_int(max_length):
parts = randint(0, (max_length - 1) / 4)
number = ['%.3d' % randint(0, 999) for _ in xrange(parts)]
left = randint(1, min(3, max_length - 4 * parts))
return '%d,%s' % (randint(1, 10 ** left - 1), str.join(',', number))
number = [str(randint(1, 10 ** left - 1))]
number.extend('%.3d' % randint(0, 999) for _ in xrange(parts))
return str.join(',', number)


def generate_string(max_length, lower=True, upper=True, digits=True,
Expand Down
21 changes: 21 additions & 0 deletions tests/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,3 +274,24 @@ class TestData:
class CycleF(models.Model):
fd = models.ForeignKey(CycleD)
f = models.IntegerField()


class AllFieldsModel(models.Model):
bigint_field = models.BigIntegerField()
int_field = models.IntegerField()
email_field = models.EmailField(max_length=40)
bool_field = models.BooleanField()
char_field = models.CharField(max_length=100)
comma_sep_int_field = models.CommaSeparatedIntegerField(max_length=20)
decimal_field = models.DecimalField()
datetime_field = models.DateTimeField()
date_field = models.DateField()
duration_field = models.DurationField()
float_field = models.FloatField()
null_bool_field = models.NullBooleanField()
pos_int_field = models.PositiveIntegerField()
small_pos_int_field = models.PositiveSmallIntegerField()
small_int_field = models.SmallIntegerField()
text_field = models.TextField(max_length=500)
time_field = models.TimeField()
gen_ip_field = models.GenericIPAddressField()
160 changes: 134 additions & 26 deletions tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,33 @@
"""
import datetime
import itertools
import models as mdls
import os
import random
import re
import tempfile
from decimal import Decimal
from django.db import models
from django.db.models import Model
from django.db.models.fields import BigIntegerField
from django.db.models.fields import BooleanField
from django.db.models.fields import CharField
from django.db.models.fields import CommaSeparatedIntegerField
from django.db.models.fields import DateField
from django.db.models.fields import DateTimeField
from django.db.models.fields import DecimalField
from django.db.models.fields import DurationField
from django.db.models.fields import EmailField
from django.db.models.fields import FloatField
from django.db.models.fields import GenericIPAddressField
from django.db.models.fields import IntegerField
from django.db.models.fields import NullBooleanField
from django.db.models.fields import PositiveIntegerField
from django.db.models.fields import PositiveSmallIntegerField
from django.db.models.fields import SmallIntegerField
from django.db.models.fields import TextField
from django.db.models.fields import TimeField
from django.test import TestCase
from djenerator.values_generator import generate_big_integer
from djenerator.values_generator import generate_boolean
from djenerator.values_generator import generate_comma_separated_int
from djenerator.values_generator import generate_date
from djenerator.values_generator import generate_date_time
from djenerator.values_generator import generate_decimal
from djenerator.values_generator import generate_email
from djenerator.values_generator import generate_int
from djenerator.values_generator import generate_integer
from djenerator.values_generator import generate_ip
from djenerator.values_generator import generate_positive_integer
from djenerator.values_generator import generate_positive_small_integer
from djenerator.values_generator import generate_small_integer
from djenerator.values_generator import generate_sentence
from djenerator.values_generator import generate_string
from djenerator.values_generator import generate_text
from djenerator.values_generator import generate_time
from djenerator.fields_generator import generate_values
from djenerator.generate_test_data import create_model
from djenerator.generate_test_data import dependencies
from djenerator.generate_test_data import dfs
Expand All @@ -48,9 +51,28 @@
from djenerator.model_reader import module_import
from djenerator.model_reader import names_of_fields
from djenerator.model_reader import relation_type
from djenerator.values_generator import generate_big_integer
from djenerator.values_generator import generate_boolean
from djenerator.values_generator import generate_comma_separated_int
from djenerator.values_generator import generate_date
from djenerator.values_generator import generate_date_time
from djenerator.values_generator import generate_decimal
from djenerator.values_generator import generate_email
from djenerator.values_generator import generate_int
from djenerator.values_generator import generate_integer
from djenerator.values_generator import generate_ip
from djenerator.values_generator import generate_positive_integer
from djenerator.values_generator import generate_positive_small_integer
from djenerator.values_generator import generate_small_integer
from djenerator.values_generator import generate_sentence
from djenerator.values_generator import generate_string
from djenerator.values_generator import generate_text
from djenerator.values_generator import generate_time
from djenerator.utility import sort_unique_tuple
from djenerator.utility import sort_unique_tuples
from djenerator.utility import unique_items
import models as mdls
from models import AllFieldsModel
from models import CycleA
from models import CycleB
from models import CycleC
Expand All @@ -77,6 +99,73 @@
from models import TestModelY


class TestFieldToRandomGeneratorMatcher(TestCase):
def test(self):
fields = list_of_fields(AllFieldsModel)
present_types = list(map(lambda field: field.__class__, fields))
field_types = [BigIntegerField, BooleanField, CharField,
CommaSeparatedIntegerField, DateField, DateTimeField,
DecimalField, DurationField, EmailField, FloatField,
GenericIPAddressField, IntegerField, NullBooleanField,
PositiveIntegerField, PositiveSmallIntegerField,
SmallIntegerField, TextField, TimeField]
self.assertFalse(set(field_types) - set(present_types),
"All types should be present." +
str(set(field_types) - set(present_types)))
for field in fields:
values = generate_values(field, 5)
self.assertLessEqual(len(values), 5)
self.assertGreaterEqual(len(values), 1)
for val in values:
if isinstance(field, IntegerField):
self.assertTrue(isinstance(val, int), val)
if isinstance(field, EmailField):
self.assertTrue(isinstance(val, str), val)
email_reg = '\w+(?:\.\w+)*@(?:[A-Za-z0-9]+\.)+[A-Za-z]+'
self.assertRegexpMatches(val, email_reg, val)
if isinstance(field, BooleanField):
self.assertTrue(isinstance(val, bool), val)
if isinstance(field, CharField):
self.assertTrue(isinstance(val, str), val)
self.assertLessEqual(len(val), field.max_length)
if isinstance(field, CommaSeparatedIntegerField):
self.assertTrue(isinstance(val, str), val)
comma_sep_int_re = '\d{1,3}(?:,\d{3})*'
self.assertRegexpMatches(val, comma_sep_int_re, val)
if isinstance(field, DateField):
self.assertTrue(isinstance(val, datetime.date), val)
if isinstance(field, DateTimeField):
self.assertTrue(isinstance(val, datetime.datetime), val)
if isinstance(field, DecimalField):
self.assertTrue(isinstance(val, Decimal), val)
if isinstance(field, FloatField):
self.assertTrue(isinstance(val, float), val)
if isinstance(field, GenericIPAddressField):
self.assertTrue(isinstance(val, str), val)
# TODO(mostafa-mahmoud): generate_ip_regex
if isinstance(field, PositiveIntegerField):
self.assertTrue(isinstance(val, int), val)
self.assertLessEqual(val, 2147483647, val)
self.assertGreaterEqual(val, 0, val)
if isinstance(field, PositiveSmallIntegerField):
self.assertTrue(isinstance(val, int), val)
self.assertLessEqual(val, 32767, val)
self.assertGreaterEqual(val, 0, val)
if isinstance(field, SmallIntegerField):
self.assertTrue(isinstance(val, int), val)
self.assertLessEqual(val, 32767, val)
self.assertGreaterEqual(val, -32768, val)
if isinstance(field, TimeField):
self.assertTrue(isinstance(val, datetime.time), val)
if isinstance(field, TextField):
self.assertTrue(isinstance(val, str), val)
self.assertLessEqual(len(val), field.max_length)
text_re = '(?:(?:\w+\s?)+.)+'
self.assertRegexpMatches(val, text_re, val)
if isinstance(field, DurationField):
self.assertTrue(isinstance(val, datetime.timedelta), val)


class TestInstanceOfDjangoModel(TestCase):
def test(self):
models = [TestModel0, TestModel1, TestModelA, TestModelB,
Expand All @@ -100,15 +189,15 @@ def test(self):
TestModelFields, SuperClass, ExtendAbstract,
ExtendSuperClass, ProxyExtend, SuperAbstract,
TestModelFieldsTwo, CycleA, CycleB, CycleC,
CycleD, CycleE, CycleF]),
CycleD, CycleE, CycleF, AllFieldsModel]),
set(list_of_models(mdls, keep_abstract=True)))
self.assertEqual(set([ExtendingModel, TestModel0, TestModel1,
TestModelA, TestModelB, TestModelC, TestModelD,
TestModelE, TestModelX, TestModelY,
TestModelFields, SuperClass, ExtendAbstract,
ExtendSuperClass, TestModelFieldsTwo,
ProxyExtend, CycleA, CycleB, CycleC, CycleD,
CycleE, CycleF]),
CycleE, CycleF, AllFieldsModel]),
set(list_of_models(mdls)))


Expand Down Expand Up @@ -500,6 +589,25 @@ def test(self):
self.assertTrue(val in r)
edges += 1
else:
this_model = field.model
while (this_model != Model and not
(hasattr(this_model, 'TestData') and
hasattr(this_model.TestData, field.name))
and not os.path.exists(
'%s/TestTemplates/sample__%s__%s' %
(this_model._meta.app_label,
this_model.__name__, field.name))):
this_model = this_model.__base__
if this_model == Model:
self.assertEqual(model.__class__,
AllFieldsModel)
sample_values = field_sample_values(field)
if val.__class__ == unicode:
val = str(val)
self.assertTrue(val.__class__ in
map(lambda val: val.__class__,
sample_values))
continue
if (field.__class__.__name__ == 'DecimalField' or
field.__class__.__name__ == 'FloatField'):
sample_values = map(float,
Expand All @@ -513,12 +621,12 @@ def test(self):
field_sample_values(field))
val = str(val)
self.assertTrue(val in sample_values)
if model.__class__ == TestModelFields:
pr = (model.fieldC, model.fieldA)
self.assertFalse(pr in pairs)
pairs.append(pr)
self.assertTrue((model.fieldB < 50)
or (model.fieldD / 2 % 2 == 1))
if model.__class__ == TestModelFields:
pr = (model.fieldC, model.fieldA)
self.assertFalse(pr in pairs)
pairs.append(pr)
self.assertTrue((model.fieldB < 50)
or (model.fieldD / 2 % 2 == 1))
self.assertTrue(all(visited.values()),
"Not all the models with sample data are generated.")

Expand Down

0 comments on commit d4701ba

Please sign in to comment.