FactoryBoy / factory_boy

A test fixtures replacement for Python

Home Page:https://factoryboy.readthedocs.io/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

TypeError: unsupported operand type(s) for -: 'Faker' and 'float'

will-afs opened this issue · comments

Description

Why isn't it possible to make operations between floats generated by faker? How to do so?

To Reproduce

@lazy_attribute
def foo_attribute(self) -> float:
    return (
            self.bar_attribute
            - self.baz_attribute
        )

with self.bar_attribute and self.baz_attribute being floats

Solved it with replacing both (that are FactoryBoy wrappers around native Faker which, oppositely to native Faker, do not support operations):

...
bar_attribute = Faker("pyfloat")
baz_attribute = Faker("pyfloat")
...

By the following:

...
bar_attribute = Faker._get_faker().pyfloat()
baz_attribute = Faker._get_faker().pyfloat()
...

Your original issue should work natively; I guess you were using faker.Faker() instead of factory.Faker().
The former is not covered by factory_boy, thus the lazy_attribute would receive an instance.

With the code you've written in your latest comment, all instances generated by the factory will have the same value for bar_attribute and baz_attribute; this is NOT what you'd expect.

The proper ways are:

class MyFactory(...):
  bar = factory.Faker("pyfloat")
  baz = factory.Faker("pyfloat")

  @factory.lazy_attribute
  def delta(self):
    return self.baz - self.bar

Or, with factory.fuzzy:

class MyFactory(...):
  bar = factory.fuzzy.FuzzyFloat()
  baz = factory.fuzzy.FuzzyFloat()

  @factory.lazy_attribute
  def delta(self):
    return self.baz - self.bar

NB: User code should NEVER need to read factory.Faker._get_faker().