Skip to main content

Provides tools to auto generate test data.

Project description

Build Status Package Version

This app aims to provide a simple way of loading masses of randomly generated test data into your development database. You can use a management command to load test data through command line.

It is named autofixture because it is based on django’s fixtures. Without autofixture you add test data through the admin to see how the non-static pages on your site look. You export data by using dumpdata to send it to your colleagues or to preserve it before you make a manage.py reset app and so on. As your site grows in complexity the process of adding and re-adding data becomes more and more annoying.

This is where autofixtures will help!

Requirements

  • We require and support Django 1.4 to 1.9

Installation

You must make the autofixture package available on your python path. Either drop it into your project directory or install it from the python package index with pip install django-autofixture. You can also use easy_install django-autofixture if you don’t have pip available.

To use the management command you must add 'autofixture' to the INSTALLED_APPS setting in your django settings file. You don’t need to do this if you want to use the autofixture package only as library.

Management command

The loadtestdata accepts the following syntax:

python manage.py loadtestdata [options] app.Model:# [app.Model:# ...]

It’s nearly self explanatory. Supply names of models, prefixed with its app name. After that, place a colon and tell the command how many objects you want to create. Here is an example of how to create three categories and twenty entries for your blogging app:

python manage.py loadtestdata blog.Category:3 blog.Entry:20

Voila! You have ready-to-use testing data populated to your database. The model fields are filled with data by producing randomly generated values depending on the type of the field. E.g. text fields are filled with lorem ipsum dummies, date fields are populated with random dates from the last year etc.

There are a few command line options available. Mainly to control the behavior of related fields. If foreingkey or many to many fields should be populated with existing data or if the related models are also generated on the fly. Please have a look at the help page of the command for more information:

python manage.py help loadtestdata

Using autofixtures as a tool for unittests

Testing the behavior of complex models has always bugged me. Sometimes models have many restrictions or many related objects which they depend on. One solution would be to use traditional fixtures dumped from your production database. But while in development when database schemes are changing frequently, it can be time consuming and sometimes difficult to deep track of changes and what each dump contains.

Autofixtures to the rescue!

Let’s start with the basics. We create an AutoFixture instance for the Entry model and tell it to create ten model instances:

>>> from autofixture import AutoFixture
>>> fixture = AutoFixture(Entry)
>>> entries = fixture.create(10)

Here are further examples for newer developers.

I have a Listing model and I want it populated with 10 objects.

>>> from autofixture import AutoFixture
>>> fixture = AutoFixture(Listing)
>>> entries = fixture.create(10)

Here I’ve added field values which allow you to default a field to a certain value rather than the random entries supplied by autofixture.

Generic Example including field_values:

from <yourapp>.models import <your model>
fixture = AutoFixture(<your model>, field_values={'<your field name>':<value>})

Specific example:

from main.models import Listing
fixture = AutoFixture(Listing, field_values={'needed_players': randint(2,10)})
entries=fixture.create(30)

In the above, I wanted the 'needed_players' (in the Session model) to have only numbers between 2 and 10, but I could have put {'needed_players': 5} if I had wanted all 'needed_players' instances to be 5.


Now you can play around and test your blog entries. By default, dependencies of foreignkeys and many to many relations are populated by randomly selecting an already existing object of the related model. But, what if you don’t have one yet? You can provide the generate_fk attribute which allows the autofixture instance to follow foreignkeys by generating new related models:

fixture = AutoFixture(Entry, generate_fk=True)

This generates new instances for all foreignkey fields of Entry. Unless the model has a foreign key reference to itself, wherein the field will be set to None if allowed or raise a CreateInstanceError. This is to prevent max recursion depth errors. It’s possible to limit this behaviour to single fields:

fixture = AutoFixture(Entry, generate_fk=['author'])

This will only create new authors automatically and doesn’t touch other tables. The same is possible with many to many fields. But you need to additionally specify how many objects should be created for the m2m relation:

fixture = AutoFixture(Entry, generate_m2m={'categories': (1,3)})

All created entry models get one to three new categories assigned.

Setting custom values for fields

As shown the the examples above, it’s often necessary to have a specific field contain a specific value. This is easily achieved with the field_values attribute of AutoFixture:

fixture = AutoFixture(Entry,
    field_values={'pub_date': datetime(2010, 2, 1)})

Limiting the set of models assigned to a ForeignKey field

You could, for example, limit the Users assigned to a foreignkey field to only non-staff Users. Or create Entries for all Blogs not belonging to Yoko Ono. Use the same construction as ForeignKey.limit_choices_to attribute:

from autofixture import AutoFixture, generators
fixture = AutoFixture(Entry, field_values={
    'blog': generators.InstanceSelector(
        Blog,
        limit_choices_to={'name__ne':"Yoko Ono's blog"})
})

Custom autofixtures

To have custom autofixtures for your model, you can easily subclass AutoFixture somewhere (e.g. in myapp/autofixtures.py)

from models import MyModel
from autofixture import generators, register, AutoFixture

class MyModelAutoFixture(AutoFixture):
    field_values = {
        'name': generators.StaticGenerator('this_is_my_static_name'),
    }

register(MyModel, MyModelAutoFixture)

Then, loadtestdata will automatically use your custom fixtures.

python manage.py loadtestdata app.MyModel:10

You can load all autofixtures.py files of your installed apps automatically like you can do with the admin autodiscover. Do so by running autofixture.autodiscover() somewhere in the code, preferably in the urls.py.

More

There is so much more to explore which might be useful to you and your projects:

  • There are ways to register custom AutoFixture subclasses with models that are automatically used when calling loadtestdata on the model.

  • More control for related models, even with relations of related models… (e.g. by using generate_fk=['author', 'author__user'])

  • Custom constraints that are used to ensure that created models are valid (e.g. unique and unique_together constraints, which are already handled by default)

Contribute

You can find the latest development version on github. Get there and fork it, file bugs or send me nice wishes.

To start developing, make sure the test suite passes:

virtualenv .env
source .env/bin/activate
pip install -r requirements/tests.txt
python setup.py test

Now go, do some coding.

Feel free to drop me a message about critiques or feature requests. You can get in touch with me by mail or twitter.

Happy autofixturing!

Changelog

0.12.1

  • #85: Better examples in README. Thanks to Dan Hitt for the patch.

  • #86: Less deprecation warnings when using django-autofixture on Python 3.5. Thanks to Nick Timkovich for the patch.

  • #87: Closing files properly, so you should see less ResourceWarnings while using django-autofixture. Thanks to Nick Timkovich for the patch.

0.12.0

  • #81: Add support for UUID fields. Thanks to @jungornti for the patch.

  • #77: Fixing a very rare crash in cases when a generated email in the UserFixture already exists. Thanks to Tien Nguyen for the patch.

0.11.0

  • #75: Support for Django 1.9. Thanks to Adam Dobrawy for the patch.

  • #67: If many to many relations are created in a autofixture, we now make sure that a registered autofixture is used for this if there is any. Thanks to Andrew Lewisohn for the patch.

0.10.1

  • Fixing unique constraint checks for multiple None values. Thanks to Andrew Lewisohn for the patch. See #66.

0.10.0

  • Supporting Django 1.7 style app configs in settings.INSTALLED_APPS when auto-importing autofixture definitions with autofixture.autodiscover.

  • Adding autofixture.generators.PositiveDecimalGenerator.

0.9.2

  • Fixed UserFixture that generated usernames with more than 30 characters.

0.9.1

  • Fixed unique constraint for models that have multiple unique_togethers set.

0.9

  • Make ImageGenerator consider the given file storage. Thanks to Andrew Pashkin for the patch.

  • Fixing check for unique constraint during data generation if the field allows to be nullable. Thanks for Andrew Pashkin for the report and fix.

0.8.0

  • Adding support for django’s ImageField. Thanks to Visgean Skeloru for the patch.

0.7.0

  • Adding AutoFixture.pre_process_instance method.

  • Allow arbitrary keyword arguments for AutoFixture.create method.

  • Fixing autofixture.unregister function.

  • Fixing UserFixture.post_process_instance.

0.6.3

  • Fixing long stated issue with GenericRelation fields. Thanks to StillNewb for the patch.

0.6.2

  • Supporting Django 1.6.

0.6.1

  • Fixing issue with models that have a selfreferencing ForeignKey field. Thanks to Josh Fyne for the patch.

0.6.0

  • Adding generators.WeightedGenerator for propabilistic selection of values. Thanks to Jonathan Tien for the idea and patch.

  • Supporting model inheritance. Thanks to Josh Fyne for the patch.

0.5.0

  • Adding FirstNameGenerator and LastNameGenerator. Thanks to Jonathan Tien for the initial patch.

  • Registered Autofixtures are used for models that are created for foreignkeys and many to many relations. Thanks to Theo Spears for the report.

0.4.0

  • Python 3 support! Though we had to drop Python 2.5 support. If you cannot upgrade to Python 2.6 by yet, please consider using the 0.3.x versions of django-autofixture. By the way: by Python 3 support, I mean, that the test suite is running without any errors. I have not tested yet the library in production for Python 3. So please test and submit bug reports if you encounter any.

0.3.2

  • DateTimeField receive timezone aware datetime objects now. Thanks to Scott Woodall for the report and patch.

  • Adding static_domain parameter to EmailGenerator to allow the production of emails that will always have the same domain. Thanks to mvdwaeter for the initial patch.

0.3.1

  • field_values were not picked up if there was a default value assigned to the field. Thanks to sirex for the report.

0.3.0

  • Adding better support for subclassing AutoFixture through merging of nested Values classes.

  • Renamed attribute and argument none_chance to better matching name empty_p for generators and none_p for AutoFixture.

  • Fixed some issues with management command options. Thanks Mikko Hellsing for his hard work.

  • Fixed issues in unregister(). Thanks Mikko Hellsing for the report.

  • Adding support for FloatField. Thanks to Jyr Gaxiola for the report.

0.2.5

  • Fixing issue with --generate-fk option in management command. Thanks Mikko Hellsing for the report and fix.

0.2.4

  • Using Autofixture.Values for defining initial values in Autofixture subclasses.

  • Making autodiscover more robust. Don’t break if some module can’t be imported or throws any other exception.

0.2.3

  • Fixing bug when a CharField with max_length smaller than 15 is used.

  • AutoFixture.field_values accepts callables as values.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django-autofixture-0.12.1.tar.gz (29.8 kB view hashes)

Uploaded Source

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page