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

AttributeError: 'Faker' object has no attribute 'generate' in FactoryBoy version 3.2.1

iannobile opened this issue · comments

Description

The generate method of the Faker class is missing.
We've been using the generate() method of the Faker wrapper class, but it appears to have been removed causing our code to fail.

To Reproduce

Here's the test we used to reproduce the problem.

import unittest
from factory import Faker

noinspection PyAttributeOutsideInit

class FactoryFakerTestCase(unittest.TestCase):
"""demo test suite to reproduce factoryboy Faker error."""

def test_faker_generate(self):
    """
    test faker generate method
    """
    first_name = "Tom"
    faker_first_name = Faker('first_name').generate()
    self.assertNotEqual(first_name, faker_first_name)

if name == 'main':
unittest.main()

Model / Factory code
# Include your factories and models here

The error occurs calling the generate method of the Faker class.

The issue

AttributeError: 'Faker' object has no attribute 'generate'

# Include the code that provoked the bug, including as full a stack-trace as possible

Traceback:
Traceback (most recent call last):
File "/simpletest.py", line 15, in test_faker_generate
faker_first_name = Faker('first_name').generate()
AttributeError: 'Faker' object has no attribute 'generate'


Sample code:
import unittest
from factory import Faker

noinspection PyAttributeOutsideInit

class FactoryFakerTestCase(unittest.TestCase):
"""demo test suite to reproduce factoryboy Faker error."""

def test_faker_generate(self):
    """
    test faker generate method
    """
    first_name = "Tom"
    faker_first_name = Faker('first_name').generate()
    self.assertNotEqual(first_name, faker_first_name)

if name == 'main':
unittest.main()

Notes

If the removal of the method was intentional, is there a recommendation on what to replace it with?

Can you explain what you are trying to do. If you’re trying to call into faker, might as well call Faker directly:

>>> import faker
>>> fake = faker.Faker()
>>> fake.first_name()
'Jordan'

We can use Faker directly, but since were already using a factory, instead of calling faker separately we just used the generate method of the faker wrapper. We used the same approach to generate data via LazyAttribute.
We can refactor to use Faker directly, but we didn't see a mention of removal of the generate method from the Faker wrapper in the release notes for 3.2.1 so we thought it was a bug.

AFAICT, that API was pretty much private (undocumented). It’s been removed in 824c6e0. I don’t think it’ll be restored.

Ok, we've gone ahead and replaced the method by directly calling Faker. In the future can you identify private methods either in the docstring or by using an underscore? Thanks.

Also ran into this after upgrade. Example of what I was doing (simplified example, perhaps you could suggest a better way)

class UserFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = User

    @factory.lazy_attribute
    def slug(self):
        company_name = factory.Faker("company").generate()
        return f"{slugify(company_name)}.myshopify.com"