FactoryBoy / factory_boy

A test fixtures replacement for Python
https://factoryboy.readthedocs.io/
MIT License
3.49k stars 392 forks source link

Passing Trait Parameter Value to SubFactory as factory.SelfAttribute Always Evaluates as True #302

Open 14droplets opened 8 years ago

14droplets commented 8 years ago

If a trait parameter passed to SubFactory not as strict True or False value, but as SelfAttrubute - it always evaluates as if True were passed.

This issue can be reproduced easilly with this example

class Foo(Base):
    """ Base model """
    __tablename__ = "foo"

    id_ = Column(Integer, primary_key=True, autoincrement=True)
    status = Column(Boolean)
    value = Column(String)

    def __str__(self):
        return "<Foo: id_: \"%d\", status\"%s\", value=\"%s\"" % (self.id_, self.status, self.value)

class FooFactory(Factory):
    """ Factory for a base model """
    class Meta:
        sqlalchemy_session = session
        model=Foo
        force_flush=True

    class Params:
        status_active = factory.Trait(
            status=True,
            value="active!"
        )

    # id_ generated automatically
    status = False
    value = "not active"

class Bar(Base):
    """ Model with a foreign key to base model `Foo` """
    __tablename__ = "bar"

    id_ = Column(Integer, primary_key=True, autoincrement=True)
    foo_id = Column(ForeignKey(Foo.id_))
    ref_foo = relation(Foo)

class BarFactory(Factory):
    """ Factory for a Bar model, that passes trait to a Foo subfactory based on a parametric value """

    class Meta:
        sqlalchemy_session = session
        model=Bar

    class Params:
        foo_status_active = False

    # id_ generated automatically
    ref_foo = factory.SubFactory(FooFactory, status_active=factory.SelfAttribute("..foo_status_active"))
    foo_id = factory.SelfAttribute(".ref_foo.id_")

print(BarFactory.create(foo_status_active=True).ref_foo)
print(BarFactory.create(foo_status_active=False).ref_foo)

(full gist at https://gist.github.com/Snork2/d88977f5bf66157f721c69363c2449f6)

This example prints

# <Foo: id_: "1", status"True", value="active!"
# <Foo: id_: "2", status"True", value="active!"

while

# <Foo: id_: "1", status"True", value="active!"
# <Foo: id_: "2", status"False", value="not active"

were expected

Environment: Python 3.5.1 (v3.5.1:37a07cee5969, Dec 6 2015, 01:38:48) [MSC v.1900 32 bit (Intel)] on win32 SQLAlchemy==1.0.12 factory-boy==2.7.0

jeffwidman commented 7 years ago

Thanks for the reproducible example.

@rbarrois is more familiar with the traits functionality... I actually haven't had the time to play with it yet. So hopefully he can take a quick peek at some point.

MarcMeszaros commented 7 years ago

Just ran into this issue as described in the original post with a similar SelfAttribute + SubFactory + Trait setup.

My setup: Python 3.4.3 Django==1.10.3 factory-boy==2.8.1