Populating PostGenerationMethodCall via Traits
See original GitHub issueConsider the following approach (with 2.11.1
):
from django.test import TestCase
import factory
class UserFactory(factory.django.DjangoModelFactory):
username = factory.Sequence(lambda n: 'USER_%03d' % n)
password = factory.PostGenerationMethodCall('set_password', 'supersecret')
class Meta:
model = 'auth.User'
class Params:
weak_password = factory.Trait(password='notsecretatall')
class PostGenerationMethodAndTraits(TestCase):
def test_populate_post_generation_through_trait(self):
user = UserFactory(weak_password=True)
self.assertTrue(user.check_password('notsecretatall'))
Which gives the following results:
Traceback (most recent call last):
File "/app/src/post_and_traits/tests.py", line 21, in test_populate_post_generation_through_trait
self.assertTrue(user.check_password('notsecretatall'))
AssertionError: False is not true
I’m not sure if this is intended behaviour or unintended, as it works with <=2.8.1
.
However, with >2.8.1
one has to redeclare the PostGenerationMethodCall
in the Trait in order to make it work:
e.g.
weak_password = factory.Trait(password=factory.PostGenerationMethodCall('set_password', 'notsecretatall'))
This could fall as far to being a design decision; whether the generation approach should have to be redeclared completely or if the generation approach should be “static”, hence the traits would only make the argument(and keywords) differ.
I’m not sure what is wanted here, although I’ve personally run in to very few cases where the method
would differ rather than only the argument(and keywords) and thus would see it fitting if one only had to write weak_password = factory.Trait(password='notsecretatall')
for changing argument for PostGenerationMethodCall
. And instead maybe use PostGeneration
for the eventual case of changing both method
and argument
.
Issue Analytics
- State:
- Created 5 years ago
- Reactions:4
- Comments:6 (1 by maintainers)
Top GitHub Comments
I’ve also just noticed the bug mentioned above. Kwargs defined inside traits don’t seem to be getting passed to any post-generation methods as they would if they were used to instantiate the factory.
Here’s an even more stripped-back example:
Everything works up until that last assertion.
Other than this (admittedly niche) issue, I love Factory Boy! I use it whenever I can. Thanks for your hard work maintainers 😃
@rbarrois
Actually, there is a bug here in that post generation isn’t being called when a trait defines an argument that should be passed to the post-generate method. Here’s a simple example:
Here’s the output of this script with version 2.11.1:
And here’s the output of this script with version 2.8.1:
IMO the functionality and output of 2.8.1 is correct: the post-generate method is run, and parameters passed to the factory constructor override parameters defined in the trait.
Thanks, and I hope this helps!