Get better autocomplete for Faker when using factory_boy

tylerlwsmith

Tyler Smith

Posted on July 27, 2024

Get better autocomplete for Faker when using factory_boy

Before language server powered autocomplete was ubiquitous, it didn't matter if code was written in a way that made autocomplete easy. Popular text editors like Sublime weren't able to understand code enough to provide meaningful suggestions. Programmers either memorized the commands of their dependencies or they referenced the documentation.

In 2024 autocomplete is everywhere, but our packages haven't necessarily made its job easy. Take this example from Factory Boy's documentation:

import factory
from datetime import datetime
from .models import User

class UserFactory(factory.Factory):
    class Meta:
        model = User

    arrival = factory.Faker(
        'date_between_dates',
        date_start=datetime.date(2020, 1, 1),
        date_end=datetime.date(2020, 5, 31),
    )
Enter fullscreen mode Exit fullscreen mode

The arrival attribute calls Faker's date_between_dates() method. Unfortunately, factory.Faker() does not tell you what Faker methods are available, and it won't tell you what parameters a Faker method accepts once you select one. This code mitigates the benefits that language servers provide.

Autocompleting Faker in factories

You can get autocomplete while using Faker with factory_boy by wrapping a Faker call in factory.LazyFunction():

import factory
from datetime import datetime
from .models import User

fake = Faker()

class UserFactory(factory.Factory):
    class Meta:
        model = User

    arrival = factory.LazyFunction(lambda: fake.date_between_dates(
        date_start=datetime.date(2020, 1, 1),
        date_end=datetime.date(2020, 5, 31),
    ))
Enter fullscreen mode Exit fullscreen mode

Functions passed to factory.LazyFunction() evaluate when the factory creates an instance. We wrap our faker call in a lambda so we can provide it arguments. And your language server can show you what parameters fake.date_between_dates() accepts.

There's less set-up when the faker function doesn't need any arguments. Here is how you could use factory.LazyFunction() with Faker's first_name() and last_name() methods:

import factory
from datetime import datetime
from .models import User

fake = Faker()

class UserFactory(factory.Factory):
    class Meta:
        model = User

    first_name = factory.LazyFunction(fake.first_name)
    last_name = factory.LazyFunction(fake.last_name)
Enter fullscreen mode Exit fullscreen mode

The biggest advantage of using factory.LazyFunction() is that it doesn't just work for Faker: you can use it to get factory_boy to call any function. The resulting code is a little longer than it would be if we had used factory.Faker(), but the assistance from the language server is worth it to me. Without it, I might need to constantly check documentation.

If it's too much to type, you can alias it to something shorter such as LazyFn:

from factory import Factory, LazyFunction as LazyFn
from datetime import datetime
from .models import User

fake = Faker()

class UserFactory(Factory):
    class Meta:
        model = User

    first_name = LazyFn(fake.first_name)
    last_name = LazyFn(fake.last_name)
Enter fullscreen mode Exit fullscreen mode
💖 💪 🙅 🚩
tylerlwsmith
Tyler Smith

Posted on July 27, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related