how to make FactoryBoy create a temporary directory?

157 Views Asked by At

I'd like to have FactoryBoy create a Django model instance for me, and then also create a temporary directory.

I've tried a few things:

class OrganizationFactory(factory.DjangoModelFactory):
    class Meta:
        model = Organization

    some_directory = tempfile.mkdtemp

and

    some_directory = tempfile.mkdtemp()

and

    @factory.lazy_attribute
    def some_directory(self):
        return tempfile.mkdtemp()

When I try to use some_directory in my tests, the value is always None.

1

There are 1 best solutions below

0
On

In order to understand what happens, the best will be to dive into factory_boy's internals.

factory_boy internals

There are separate phases in a Factory's life:

  1. The declaration

When Python imports the module containing a class Factory declaration, that class's definition is handled to a special metaclass in factory_boy's source code. The metaclass reads all defined class attributes and methods, analyses them, and stores them in a specific way.

  1. Using the factory

When your code uses MyFactory(), the class starts building an instance, according to the following steps:

  1. Evaluate the declarations: each LazyAttribute, SubFactory, etc. is asked to generate its value;
  2. Pass the resulting parameters to the Meta.model class constructor ­— this provides an instance of said class;
  3. Ask all post-generation declarations (RelatedFactory and co) to work on the generated object — note that any value returned from those declarations is thrown away
  4. Return the instance.

Solving your issue

In your case, I believe the issue might be that some_directory is either not a valid kwarg for your model's __init__, or replaced by some magic on your model class.

The simplest way would be to work on the post-generation level:

class OrganizationFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = Organization

    @factory.post_generation
    def some_directory(org, *args, **kwargs):
        tmpdir = tempfile.mkdtemp()
        # Attach the generated temporary directory to the generated organization.
        org.some_directory = tmpdir