pytest-factoryboy icon indicating copy to clipboard operation
pytest-factoryboy copied to clipboard

Factories behave differently as fixtures when there's a related model?

Open dragonpaw opened this issue 4 years ago • 0 comments

(I really have no clue what to title this ticket.)

What I'm seeing though is that when I register a factory, the model fixture behaves differently when it's called vs. just a bare invocation of the factory.

Here's the code for some Tags I'm trying to test, which have a related Type:

# factories.py
class TagTypeFactory(factory.django.DjangoModelFactory):

    name = factory.Sequence(lambda n: "type_%d" % n)
    unique = factory.Faker("boolean")
    color = factory.Faker("hex_color")
    created_by = factory.SubFactory(UserFactory)
    updated_by = factory.LazyAttribute(lambda obj: obj.created_by)

    class Meta:
        model = "common.TagType"
        django_get_or_create = ("name",)


class TagFactory(factory.django.DjangoModelFactory):

    name = factory.Sequence(lambda n: "tag_%d" % n)
    description = factory.Faker("bs")
    type = factory.SubFactory(
        factory=TagTypeFactory,
        name=TagType.MISC_NAME,
    )
    created_by = factory.SubFactory(UserFactory)
    updated_by = factory.LazyAttribute(lambda obj: obj.created_by)
    slug = factory.LazyAttribute(lambda obj: f"{obj.type.name}:{obj.name}".lower())

    class Meta:
        model = "common.Tag"
        django_get_or_create = ("name",)

The idea here is that the default name of TagType.MISC_NAME will be used for all tags, unless I need a different type. like so:

In [3]: TagFactory()
Out[3]: <Tag: tag_0 (miscellaneous)>

In [6]: TagTypeFactory()
Out[6]: <TagType[13] n:type_3: s:False, a:True>

In [7]: TagTypeFactory(name='service')
Out[7]: <TagType[3] n:service: s:True, a:True>

This works to lookup pre-populated tags because I'm using django_get_or_create on the factories so name arguments can be existing tags/types.

But when I register the TagFactory, and call the 'tag' fixture, from another fixture like so:

def fixture_user(tag) -> User:
    logger.debug("Tag for user fixture: %r", tag)

I get a Tag with a different type than I'd expect:

DEBUG Tag for user fixture: <Tag: tag_1 (type_1)>

dragonpaw avatar Sep 10 '21 19:09 dragonpaw