-
Notifications
You must be signed in to change notification settings - Fork 41
Description
Continuation of #91 as I believe it was closed in error and I cannot reopen it.
The issue still remains that if a Factory class has a SubFactory defined that is a subclass of a different factory, the generated fixture does not correctly insert the right sub factory. Here is an example:
Code sample with failing test
import factory
from pytest_factoryboy import register
class AModel:
"""Simple model that refers to another model"""
def __init__(self, b_model):
self.b_model = b_model
class BModel:
"""The referred to model by A that has a name."""
def __init__(self, name):
self.name = name
class BModelFactory(factory.Factory):
"""Factory that creates B models."""
class Meta:
model = BModel
name = "John"
class BobModelFactory(BModelFactory):
"""Factory class inheritance to create a specialized model factory as recommended by
the FactoryBoy docs.
https://factoryboy.readthedocs.io/en/stable/introduction.html#inheritance
"""
name = "Bob"
class AModelFactory(factory.Factory):
"""Factory that creates A models using a SubFactory to set the b_model attribute."""
class Meta:
model = AModel
b_model = factory.SubFactory(BobModelFactory)
register(BModelFactory)
register(BobModelFactory, "b_model_bob")
register(AModelFactory)
def test_wrong_fixture_name(a_model):
"""This test fails because the a_model.b_model fixture ends up being BModelFactory
instead of the BobModelFactory that is defined as the SubFactory in AModelFactory.
"""
assert a_model.b_model.name == "Bob"I believe the issue follows from:
- pytest-factoryboy uses the model class's name, not the factory class's name, to define the model fixture name. This means that any factory classes that inherit from a common factory class will overwrite any previously registered model factory fixtures with the most recently registered factory.
- To avoid the naming issue, factory subclasses of the common parent must be registered with a different model fixture name.
- Since the subfactory fixture name lookup seems to be based on the model class's name and not the factory class's name, the resolved subfactory fixture name ends up using the wrong model fixture.
The lazy fixture suggestion using partial fixture specialization during register seems like a valid workaround, but is not what I would consider the fix. It is surprising behavior that I can define AModelFactory to use BobModelFactory as the sub factory, but instead get BModelFactory used as the subfactory because of how pytest-factoryboy generates and resolves fixtures. This kind of factory inheritance and sub factory usage works as expected when using factoryboy directly.