autofactory

AutoFactoryBoy generates factories for you.


Keywords
autofactory, django, python, testing
License
MIT
Install
pip install autofactory==0.3.0

Documentation

AutoFactoryBoy

Build Status PyPI Package

Warning! AutoFactoryBoy supports only Django ORM for now.

AutoFactoryBoy introspects ORM models and generates factories.

Contents

Installation

Install from PyPI:

$ pip install autofactory

Build from source:

$ git clone git://github.com/nickgashkov/autofactoryboy/
$ python setup.py install

Quickstart

There are a couple of options to create an AutoFactory for a model:

  1. Subclass a DjangoModelAutoFactory:

    from autofactory.django import DjangoModelAutoFactory
    
    from models import Model
    
    class ModelFactory(DjangoModelAutoFactory):
        class Meta:
            model = Model
            autofields = "__all__"
    
    model = ModelFactory.create(some__field__to__change=42)
  2. Make a factory right from the model with the help of a shortcut:

    from autofactory.django import autofactory
    
    from models import Model
    
    model_factory = autofactory(Model)
    model = model_factory.create(some__field__to__change=42)

Compatibility

Python Django SQLAlchemy Mogo mongoengine
2.7 1.11 — — —
3.4 1.11, 2.0 — — —
3.5 1.11, 2.0, 2.1 — — —
3.6 1.11, 2.0, 2.1 — — —
3.7 1.11, 2.0, 2.1 — — —

Q & A

How do I make an autofactory with specific fields?

AutoFactoryBoy will generate a ModelFactory for a model with fields, declared in the ModelFactory.Meta:

class ModelFactory(DjangoModelAutoFactory):
    class Meta:
        model = Model
        autofields = ("integer", "string")

The code snippet above is identical to:

class ModelFactory(DjangoModelFactory):
    integer = factory.Faker("pyint")
    string = factory.Faker("text")

    class Meta:
        model = Model

How do I make an autofactory with all model fields?

You can set fields to a special value (i.e. __all__) and all fields with blank=False and without default will be generated automatically:

# models.py
class Model(models.Model):
    integer = models.IntegerField(blank=True, null=True)
    text = models.TextField(default="Default")
    string = models.CharField(max_length=20)

# factories.py
class ModelFactory(DjangoModelAutoFactory):
    class Meta:
        model = Model
        autofields = "__all__"

The code snippet above is identical to:

class ModelFactory(DjangoModelFactory):
    string = factory.Faker("text", max_nb_chars=20)

    class Meta:
        model = Model

How do I make an autofactory with all model fields except one

You can add the field you want to exclude to the Meta.autoexclude tuple:

# models.py
class Model(models.Model):
    field = models.IntegerField(blank=False, null=True)
    field_to_exclude = models.IntegerField(blank=False, null=True)

# factories.py
class ModelFactory(DjangoModelAutoFactory):
    class Meta:
        model = Model
        autoexclude = ("field_to_exclude",)

The code snippet above is identical to:

class ModelFactory(DjangoModelFactory):
    field = factory.Faker("pyint")

    class Meta:
        model = Model

Warning! One cannot set autofields and autoexclude for one factory at the same time.

How do I teach AutoFactoryBoy how to generate my custom field

Make a custom builder and register it with decorator or as a function:

# models.py
class Model:
    custom = CustomField()

# builders.py
from autofactory.django.builders import registry

@registry.register(CustomField)
def build_custom_field(field_cls):
    ...

registry.register(CustomField, build_custom_field)

Warning! Order is important. Make sure, that you register all custom fields before any factory declaration. I.e.:

from autofactory.django.builders import registry, FROM_DEFAULT
from autofactory.django import autofactory, DjangoModelAutoFactory

from models import Model


# Register first.
registry.register(FROM_DEFAULT, lambda x: "Default for everything")


# Declare second.
class ModelFactory(DjangoModelAutoFactory):
    class Meta:
        model = Model
        autofields = "__all__"

model_factory = autofactory(Model)

How do I override AutoFactoryBoy field builder

autofactory.django.builders.registry for the rescue! Using the approach above, you can redeclare builder for any field:

from autofactory.django.builders import registry

from django.db import models


@registry.register(models.CharField)
def custom_char_field_builder(field_cls):
    ...

Contributing

Dependencies

To install dev dependencies, run:

$ pip install pip-tools
$ make upgrade

Code formatting

To format the code, run:

$ make 

Testing

To test, run:

$ make test      # Current environment
$ make test-tox  # All tox environments

License

This project is licensed under the MIT License — see the LICENSE file for details.

Acknowledgments