paulocheque / django-dynamic-fixture

A complete library to create dynamic model instances for testing purposes.
http://django-dynamic-fixture.readthedocs.io/
Other
390 stars 67 forks source link

String masks should be allowed as lessons for unique fields #152

Closed PoByBolek closed 1 year ago

PoByBolek commented 1 year ago

I have a class with a unique field that I want to fill using string masks in my tests. For example:

### models.py
from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=100, unique=True)

### tests.py
from django.test import TestCase
from django_dynamic_fixture import G, M, teach

from demo.models import Person

teach(Person, name=M('-_______ -_____________'))

class PersonTest(TestCase):
    def test_stuff(self):
        self.assertNotEqual(G(Person).name, G(Person).name)

But when I try to run the tests using python manage.py test this raises the following exception (even though the string mask is not a static value):

Found 1 test(s).
System check identified no issues (0 silenced).
E
======================================================================
ERROR: demo.tests (unittest.loader._FailedTest)
----------------------------------------------------------------------
ImportError: Failed to import test module: demo.tests
Traceback (most recent call last):
  File "C:\Program Files\Python38\lib\unittest\loader.py", line 436, in _find_test_path
    module = self._get_module_from_name(name)
  File "C:\Program Files\Python38\lib\unittest\loader.py", line 377, in _get_module_from_name
    __import__(name)
  File "C:\Users\demo\demo\tests.py", line 7, in <module>
    teach(Person, name=M('-_________ -______________'))
  File "<string>", line 9, in teach
  File "C:\Users\demo\venv\lib\site-packages\django_dynamic_fixture\__init__.py", line 177, in _teach
    return d.teach(model, ddf_lesson=ddf_lesson, **kwargs)
  File "C:\Users\demo\venv\lib\site-packages\django_dynamic_fixture\ddf.py", line 690, in teach
    raise InvalidConfigurationError('It is not possible to store static values for fields with unique=True (%s). Try using a lambda function instead.' % get_unique_field_name(field))
django_dynamic_fixture.ddf.InvalidConfigurationError: It is not possible to store static values for fields with unique=True (demo.models.Person.name). Try using a lambda function instead.

However, when I remove the unique=True constraint, everything works perfectly fine and the test (G(Person).name != G(Person).name) succeeds.

I feel like DynamicFixture.teach() should also allow string masks here.

https://github.com/paulocheque/django-dynamic-fixture/blob/ce0d3deb895360ec2b57b98037a13573967c94f6/django_dynamic_fixture/ddf.py#L682-L691


I currently work around this using a lambda expression, but allowing a string mask directly would be much nicer 😸

teach(Person, name=lambda field: M('-________ -____________').evaluate())
paulocheque commented 1 year ago

Nice catch! Do you think this could be a fix?

if field.unique and not (isinstance(fixture, (DynamicFixture, Copier, DataFixture, Mask)) or callable(fixture)): 

instead of

if field.unique and not (isinstance(fixture, (DynamicFixture, Copier, DataFixture)) or callable(fixture)): 
PoByBolek commented 1 year ago

This would fix my issue at hand, yes 👍

jheld commented 1 year ago

So this is only in test code?

PoByBolek commented 1 year ago

Any progress on this? I'd be happy to provide a pull request for this if you don't have time right now...

paulocheque commented 1 year ago

Any progress on this? I'd be happy to provide a pull request for this if you don't have time right now...

That would be great! Then I can generate a new release.

paulocheque commented 1 year ago

Thanks guys. I released the 3.1.3 version, but it was the first time using Twine for that, so if there is any problem with that release, please let me know.

I am planning to release a 4.0.0 version later discarding support for Python 2 and old Django versions. That should clean up the code to facilitate new contributions.