berinhard / model_mommy

No longer maintained, please migrate to model_bakery
http://model-bakery.readthedocs.org/
Other
903 stars 141 forks source link

mommy.make should check for uniqueness #82

Closed fernandogrd closed 11 years ago

fernandogrd commented 11 years ago

When the field have unique constraint (ex: a IntegerField code) and I do something like: bobs_dog = mommy.make('family.Dog',)

I get random duplicate errors like: IntegrityError: duplicate key value violates unique constraint "app_model_code_key"

berinhard commented 11 years ago

@fernandogrd I think model_mommy should deal with cases that accepts random generation and do not have constraints. For example, in this case, since the field is have a unique constraint, I think that is test responsibility to deal with this constraint. And, if I'm not wrong, this is kind of a rare case, right? I mean, IntegerField generation are quite reliable on generating random and different values. Although this could be a problem to other type of fields.

fernandogrd commented 11 years ago

It is rare, but very annoying when it happens. I'll investigate further to see if there is something more contributing to this. It certainly happened more than once with a not so big data set, so, maybe is something in details.

One more thing I did post wrong is that my model does not have an integer field, but a foreign key to a model that have the (positive) integer unique field.

In one of tests, I was generating 12 instances, so I tried to do a very unscientific test:

c = 0
while True:
    c += 1
    if (len(set([random.randint(0, 10000) for i in range(12)]))) < 12:
        break

The smallest number of iterations I get was 9, after a few tries, I get lots of values lower than 100 iterations. It takes a lot longer if the max number is higher than 10000

After these, I realise I do not want to have these related instances beeing generated the 12 times, so I should just attribute one generated once.

To reduce the chance of having duplicate integers, we could set MAX_INT to a bigger number. But I would still fell a bit unconfortable with the possibily of random failures in tests. https://github.com/vandersonmota/model_mommy/blob/master/model_mommy/generators.py#L28

berinhard commented 11 years ago

@fernandogrd another approach to solve this problem is to change IntegerField random generator. Maybe we could use Python generators to do the job. I think something as the following example is no too complicated to write (obviously we would raise the upper range limit):

def python_gen():
    for i in range(0, 5):
        yield i

integer_gen = python_gen()

MAX_INT = 10
def gen_integer():
    global integer_gen
    try:
        return integer_gen.next()
    except StopIteration:
        integer_gen = python_gen()
        return integer_gen.next()

print " 1 - %d" % gen_integer()
print " 2 - %d" % gen_integer()
print " 3 - %d" % gen_integer()
print " 4 - %d" % gen_integer()
print " 5 - %d" % gen_integer()
print " 6 - %d" % gen_integer()
print " 7 - %d" % gen_integer()
print " 8 - %d" % gen_integer()
print " 9 - %d" % gen_integer()
print "10 - %d" % gen_integer()

The output should be:

 1 - 0
 2 - 1
 3 - 2
 4 - 3
 5 - 4
 6 - 0
 7 - 1
 8 - 2
 9 - 3
10 - 4

If @vandersonmota is ok with this approach, I'll be happy to write a patch.

fernandogrd commented 11 years ago

Looks awesome! =)

vandersonmota commented 11 years ago

I just created the 'sequences' concept. I think it will fit those cases. See docs. =)

berinhard commented 11 years ago

@vandersonmota this solves the problem it has a downside that forces the developer to write Recipes. This does not sounds very good for me because I'm used to use Recipes for fixed and well determined values. But I'm a +1 for merging your branch into master while we do not think about other solution for this problem.

If anyone else wanna see the code, it's in this branch.

vandersonmota commented 11 years ago

Well, since the ommited fields will be generated automatically, It will be a short recipe. =)

Personally, i don't see the problem recipes are a set of rules to be applied in object creation, using a declarative api.

fernandogrd commented 11 years ago

I like it a lot, and as it is documented, I think it'll avoid people having this problem.

About the downside of the need to write the recipe, the thing that attract me to model mommy is the fact of not need to write recipes for most of cases, with other solutions I needed to write recipes for everything and I find this annoying.

big ps.: just recently started using model mommy