A full library to create dynamic model instances for testing purposes.
Project description
=Description=
A full library to create dynamic model instances for testing purposes.
=Installation=
pip install django-dynamic-fixture
or
# Download zip file
# Extract it
# Execute in the extracted directory: python setup.py install
=Upgrade=
pip install django-dynamic-fixture --upgrade --no-deps
=Motivation=
* It is a TERRIBLE practice to use STATIC data in tests.
* Create dynamic fixture for each model is boring and it produces a lot of replicated code.
* It is a bad idea to use uncontrolled data in tests, like bizarre random data.
=Comparison with another fixture tools=
* We tried to use another fixture tools in a big Django project but the experience was not satisfactory.
* Either they are incomplete, or bugged or it produces erratic tests, because they use random and uncontrolled data.
* Also, the syntax of others tools is too verbose, which polutes the tests.
* Complete, lean and practice documentation.
* It is hard to debug tests with another tools.
* List of other tools: http://djangopackages.com/grids/g/fixtures
=Features=
* Highly customizable: you can customize fields recursively
* Deal with unique=True
* Deal with cyclic dependencies (including self references)
* Deal with many to many relationship (common M2M or M2M with additional data, i.e. through='table')
* Deal with custom fields (specially if the custom field inherit of a django field)
* It is supported for parallel tests
* Deal with auto calculated attributes
* It is easy to debug errors
=Example of Usage=
{{{
from django_dynamic_fixture import N, G, F, P
#or use old default names:
#from django_dynamic_fixture import new, get, DynamicFixture as F, print_field_values
# Models:
from django.db import models
class ModelA(models.Model): pass
class ModelY(models.Model):
other_text = models.CharField()
other_list = models.ManyToManyField('ModelA')
class ModelX(models.Model):
some_text = models.CharField(null=True)
parent_left = models.ForeingKey('self')
y_reference = models.ForeingKey('ModelY')
list_a = models.ManyToManyField('ModelA')
# Summary:
# DynamicFixture (F): receive arguments and create model instances.
# new: it is just a wrapper: it creates a F to create a not saved model instance.
# get: basically, call the new method and save the instance. You can set ManyToMany fields only after the instance is saved.
# Examples:
instance_of_modelx = N(ModelX)
assert instance_of_modelx.some_text != None
assert instance_of_modelx.parent_left != None
assert instance_of_modelx.parent_left.parent_left == None
assert instance_of_modelx.id == None # new do not save the instance
assert instance_of_modelx.y_reference.id != None # save dependencies by default
assert len(instance_of_modelx.list_a.all()) == 0 # do not create many2many fields by default
instance_of_modelx = N(ModelX, fill_nullable_fields=False) # default = True
assert instance_of_modelx.some_text == None
# you can ignore fields, but do not ignore required fields (with null=False).
instance_of_modelx = G(ModelX, ignore_fields=['some_text'])
assert instance_of_modelx.some_text == None
# Very nice feature to work with trees
instance_of_modelx = N(ModelX, number_of_laps=2) # default = 1
assert instance_of_modelx.parent_left != None
assert instance_of_modelx.parent_left.parent_left != None
assert instance_of_modelx.parent_left.parent_left.parent_left == None
# This feature is specially useful to test search methods
instance_of_modelx = N(ModelX, some_text='some fixed data') # attribute accepts static data
assert instance_of_modelx.some_text == 'some fixed data'
# Use this with attention. First, check for design mistakes
instance_of_modelx = N(ModelX, id=99999) # you can define the id too
assert instance_of_modelx.id == 99999
# You can create your own function to create data..
instance_of_modelx = N(ModelX, some_text=lambda field: field.name) # attribute accepts callables
assert instance_of_modelx.some_text == 'some_text'
# Use this with attention, you can get an error if you try to save an instance with not saved dependencies
instance_of_modelx = N(ModelX, persist_dependencies=False)
assert instance_of_modelx.y_reference.id == None
instance_of_modelx = G(ModelX) # get save the model instance
assert instance_of_modelx.id != None
instance_of_modelx = G(ModelX, list_a=2) # Many2Many can receive a number of instances to be created
assert len(instance_of_modelx.list_a.all()) == 2
instance_of_modelx = G(ModelX, list_a=[F(), F(), F()]) # Many2Many can receive a list of DynamicFixtures
assert len(instance_of_modelx.list_a.all()) == 3
a = G(ModelA)
instance_of_modelx = G(ModelX, list_a=[F(), a, F()]) # Many2Many can receive a list of instances
assert len(instance_of_modelx.list_a.all()) == 3
# You can pass arguments to F (DynamicFixture) recursively. This works for ForeignKey and ManyToMany Fields! Easy and customizable!
instance_of_modelx = G(ModelX, parent_left=F(other_text='wow', other_list=2))
assert len(instance_of_modelx.y_reference.other_list.all()) == 2
# Highly recursivable example:
# X has a ForeignKey to A
# A has a ForeignKey to B
# B has a ForeignKey to C
# this will create instances of C, B, A and X (in this order). Attribute d of C will be 'some value'
G(X, a=F(b=F(c=F(d='some value'))))
# for debug:
P(instance_of_modelx)
# Custom FileField:
class ModelX(models.Model):
my_file = models.FileField(upload_to='/')
from tempfile import mkstemp
pdf_a = File(open(mkstemp()[1], 'w'), name='a.pdf')
G(ModelX, my_file=pdf_a)
}}}
== Decorators ==
{{{
from django_dynamic_fixture.decorators import skip_for_database, only_for_database, SQLITE3
@only_for_database(SQLITE3)
def test_something1(self): pass
@skip_for_database(SQLITE3)
def test_something2(self): pass
@only_for_database("some value used in settings.DATABASES['default']['ENGINE']")
def test_something3(self): pass
@skip_for_database("some value used in settings.DATABASES['default']['ENGINE']")
def test_something4(self): pass
}}}
== Queries Module ==
{{{
python manage.py test --with-queries
python manage.py count_queries_on_save
}}}
=Information about the logic of the library=
==List of exceptions==
* UnsupportedFieldError: DynamicFixture does not support this field.
* InvalidConfigurationError: The specified configuration for the field can not be applied or it is bugged.
* InvalidManyToManyConfigurationError: M2M attribute configuration must be a number or a list of DynamicFixture or model instances.
* BadDataError: The data passed to a field has some problem (not unique or invalid) or a required attribute is in ignore list.
==DynamicFixture assume==
* if a field has a default value, it does not have unique=True.
* if a field has choices, it does not have unique=True.
* if there is a cyclic dependency, in some part the relationship must be nullable.
* if any of these requirements is a problem, you have to use customized values or override the behavior.
==DynamicFixture rules==
===General===
* The id (AutoField) is auto filled, unless you set a value to it.
* if a field has default value, it will be used by default.
* if a field has choices, it select each the first option by default.
* it fill nullable fields with data unless fill_nullable_fields is False.
* boolean fields will always receive False, unless it has default value.
* null boolean fields will always receive None, unless it has default value.
* Strings (CharField, Text, Url, Email...) and numbers (IntegerField, Float, Decimal...) are filled with a sequential and unique number for each test (1, '1', 2, '2'...). Each attribute has its own counter.
* You can override the behavior of the string and number fillers, if you want to.
===Custom Attributes===
* if it receive a customized data, it do not care about attributes null, unique, default or choices.
* if the specified fixture was bugged, it will raise an InvalidConfigurationError.
===Custom Fields===
* if it does not recognize the Field class, it will raise an UnsupportedFieldError.
* if a field is not default in Django, but it inherits from a Django field, it will be filled using its config.
* if a field is not default in Django and not related with a Django field, it will raise an UnsupportedFieldError.
* Customized data is also valid for unsupported fields.
===Related Objects===
* ForeignKey will be filled by default, considering unicity of data.
* It deal with cyclic dependencies, including self references (this avoid infinite recursion).
* By default, the fixture create just one cycle, but it is possible to specify more maps with number_of_laps parameter.
===Many to Many relationship===
* To add models in a m2m relation, the model must be persisted, so use the 'get' method.
* it expect to receive a parameter with the amount of instances that need to be created (using default configuration).
* Also, it can receive a list with DynamicFixture (F) or model instances (for custom items). The size of the list is the number of items that will be created.
* It works for default Many2Many and Many2Many with through.
===Ignoring fields===
* Useful when some fields need some calculation. For example, Django-MPTT models.
* Ignored fields are propagated ONLY to self references.
* Do not ignore required fields with 'get', only with 'new'. In other words, do not save an instance without a required field, unless you are expecting for an exception.
===Patterns===
* Use 'new' method for unit tests (not integration tests) for the main model.
* Use 'ignore_fields' option to deal with fields filled by listeners.
* Use custom values for unsupported fields.
* Use 'number_of_laps' option to test trees.
===Anti-Patterns===
* Use a auto generated data in an assertion method.
=Links of Comments=
* http://www.reddit.com/r/django/comments/fv1re/django_dynamic_fixture
* http://djangopackages.com/grids/g/fixtures/
* http://news.ycombinator.com/item?id=2275406
* http://pythonsmalltalk.blogspot.com/2011/02/django-dynamic-fixture.html
* http://pythonsmalltalk.blogspot.com/2011/03/django-dynamic-fixture-121.html
* http://pypi.python.org/pypi/django-dynamic-fixture/1.2
* http://code.activestate.com/pypm/django-dynamic-fixture
* http://groups.google.com/group/django-mptt-dev/browse_thread/thread/d9eb9e22ad4aa656
* http://groups.google.com/group/django-users/browse_thread/thread/1346a60008c21a7b
* http://groups.google.com/group/django-brasil/browse_thread/thread/757df09d3c3be81d
* http://linux.softpedia.com/get/Internet/HTTP-WWW-/django-dynamic-fixture-68711.shtml
=Change Log=
==Version 1.5.0==
* 2012/03/24 (yyyy/mm/dd)
* http://pypi.python.org/pypi/django-dynamic-fixture/1.5.0
* New features in DDF:
* global settings: DDF_DEFAULT_DATA_FIXTURE, DDF_FILL_NULLABLE_FIELDS, DDF_IGNORE_FIELDS, DDF_NUMBER_OF_LAPS, DDF_VALIDATE_MODELS
* new data fixture that generates random data
* new data fixture that use sequential numbers only for fields that have unique=True
* P function now accept a list of model instances
* Option to call model_instance.full_clean() validation method before saving the object (DDF_VALIDATE_MODELS).
* Validate field names. If a invalid field name is passed as argument, it will raise an InvalidConfigurationError exception.
* DateField options 'auto_add_now' and 'auto_add' are disabled if a custom value is used.
==Version 1.4.3==
* 2012/02/23 (yyyy/mm/dd)
* http://pypi.python.org/pypi/django-dynamic-fixture/1.4.3
* Bugfix in ForeignKeys with default values
==Version 1.4.2==
* 2011/11/07 (yyyy/mm/dd)
* http://pypi.python.org/pypi/django-dynamic-fixture/1.4.2
* Bugfix in FileSystemDjangoTestCase
==Version 1.4.1==
* 2011/11/07 (yyyy/mm/dd)
* http://pypi.python.org/pypi/django-dynamic-fixture/1.4.1
* New features in DDF:
* Now you can set a custom File to a FileField and the file will be saved in the file storage system.
* New features in FileSystemDjangoTestCase:
* create_django_file_using_file create a django.File using the content of your file
* create_django_file_with_temp_file now accepts a content attribute that will be saved in the generated file
* Bugfix in FileSystemDjangoTestCase:
* now create_django_file_with_temp_file close the generated file
==Version 1.4.0==
* 2011/10/29 (yyyy/mm/dd)
* http://pypi.python.org/pypi/django-dynamic-fixture/1.4.0
* New features:
* Nose plugin to count queries on each test
* Command line to count queries on the save (insert and update) of each model
* Bugfixes in DDF:
* Field with choice and default must use the default value, not the first choice value
* Validation if the class is a models.Model instance
* Showing all stack trace, when an exception occurs
* Bugfixes in decorators: default values of database engines were not used correctly
* Bugfixes in FileSystemDjangoTestCase tests
==Version 1.3.1==
* 2011/10/03 (yyyy/mm/dd)
* http://pypi.python.org/pypi/django-dynamic-fixture/1.3.1
* Bugfixes in FileSystemDjangoTestCase
==Version 1.3.0==
* 2011/10/03 (yyyy/mm/dd)
* http://pypi.python.org/pypi/django-dynamic-fixture/1.3.0
* New Feature: File System Django Test Case
* New Feature: Decorators skip_for_database and only_for_database
* Bugfix: Inheritance problems, before this version the DDF filled fields with the attribute parent_link
==Version 1.2.3==
* 2011/06/27 (yyyy/mm/dd)
* http://pypi.python.org/pypi/django-dynamic-fixture/1.2.3
* Bugfix in string truncation to max_length
==Version 1.2.2==
* 2011/05/05 (yyyy/mm/dd)
* http://pypi.python.org/pypi/django-dynamic-fixture/1.2.2
* Improvements in exception messages
==Version 1.2.1==
* 2011/03/11 (yyyy/mm/dd)
* http://pypi.python.org/pypi/django-dynamic-fixture/1.2.1
* Propagate ignored fields to self references
* Refactoring + Bug fixes
==Version 1.2==
* 2011/03/04 (yyyy/mm/dd)
* http://pypi.python.org/pypi/django-dynamic-fixture/1.2
* New Feature: ignore_fields
* New Feature: now it is possible to set the ID
==Version 1.1==
* Bug fixes
* http://pypi.python.org/pypi/django-dynamic-fixture/1.0 (1.0 has the 1.1 package)
==Version 1.0==
* Initial version
* Ready to use in big projects
= Testing =
* python manage.py test
* python manage.py test --with-coverage --cover-inclusive --cover-html --cover-package=django_dynamic_fixture.* --with-queries
= TODO List =
* auto config of denormalizated fields
* with_queries documentation and bugfixes (always print 0 queries)
* related_name documentation or workaround
* today, yesterday, tomorrow on fdf
* bugfix in fdf or ddf: some files/directories are not deleted
* tests with files in ddf
* tests with proxy models
* doc factory: example to generate models with validators in fields or in clean methods
* tests with GenericRelations, GenericForeignKey etc
* more tests with OneToOneField(parent_link=True)
A full library to create dynamic model instances for testing purposes.
=Installation=
pip install django-dynamic-fixture
or
# Download zip file
# Extract it
# Execute in the extracted directory: python setup.py install
=Upgrade=
pip install django-dynamic-fixture --upgrade --no-deps
=Motivation=
* It is a TERRIBLE practice to use STATIC data in tests.
* Create dynamic fixture for each model is boring and it produces a lot of replicated code.
* It is a bad idea to use uncontrolled data in tests, like bizarre random data.
=Comparison with another fixture tools=
* We tried to use another fixture tools in a big Django project but the experience was not satisfactory.
* Either they are incomplete, or bugged or it produces erratic tests, because they use random and uncontrolled data.
* Also, the syntax of others tools is too verbose, which polutes the tests.
* Complete, lean and practice documentation.
* It is hard to debug tests with another tools.
* List of other tools: http://djangopackages.com/grids/g/fixtures
=Features=
* Highly customizable: you can customize fields recursively
* Deal with unique=True
* Deal with cyclic dependencies (including self references)
* Deal with many to many relationship (common M2M or M2M with additional data, i.e. through='table')
* Deal with custom fields (specially if the custom field inherit of a django field)
* It is supported for parallel tests
* Deal with auto calculated attributes
* It is easy to debug errors
=Example of Usage=
{{{
from django_dynamic_fixture import N, G, F, P
#or use old default names:
#from django_dynamic_fixture import new, get, DynamicFixture as F, print_field_values
# Models:
from django.db import models
class ModelA(models.Model): pass
class ModelY(models.Model):
other_text = models.CharField()
other_list = models.ManyToManyField('ModelA')
class ModelX(models.Model):
some_text = models.CharField(null=True)
parent_left = models.ForeingKey('self')
y_reference = models.ForeingKey('ModelY')
list_a = models.ManyToManyField('ModelA')
# Summary:
# DynamicFixture (F): receive arguments and create model instances.
# new: it is just a wrapper: it creates a F to create a not saved model instance.
# get: basically, call the new method and save the instance. You can set ManyToMany fields only after the instance is saved.
# Examples:
instance_of_modelx = N(ModelX)
assert instance_of_modelx.some_text != None
assert instance_of_modelx.parent_left != None
assert instance_of_modelx.parent_left.parent_left == None
assert instance_of_modelx.id == None # new do not save the instance
assert instance_of_modelx.y_reference.id != None # save dependencies by default
assert len(instance_of_modelx.list_a.all()) == 0 # do not create many2many fields by default
instance_of_modelx = N(ModelX, fill_nullable_fields=False) # default = True
assert instance_of_modelx.some_text == None
# you can ignore fields, but do not ignore required fields (with null=False).
instance_of_modelx = G(ModelX, ignore_fields=['some_text'])
assert instance_of_modelx.some_text == None
# Very nice feature to work with trees
instance_of_modelx = N(ModelX, number_of_laps=2) # default = 1
assert instance_of_modelx.parent_left != None
assert instance_of_modelx.parent_left.parent_left != None
assert instance_of_modelx.parent_left.parent_left.parent_left == None
# This feature is specially useful to test search methods
instance_of_modelx = N(ModelX, some_text='some fixed data') # attribute accepts static data
assert instance_of_modelx.some_text == 'some fixed data'
# Use this with attention. First, check for design mistakes
instance_of_modelx = N(ModelX, id=99999) # you can define the id too
assert instance_of_modelx.id == 99999
# You can create your own function to create data..
instance_of_modelx = N(ModelX, some_text=lambda field: field.name) # attribute accepts callables
assert instance_of_modelx.some_text == 'some_text'
# Use this with attention, you can get an error if you try to save an instance with not saved dependencies
instance_of_modelx = N(ModelX, persist_dependencies=False)
assert instance_of_modelx.y_reference.id == None
instance_of_modelx = G(ModelX) # get save the model instance
assert instance_of_modelx.id != None
instance_of_modelx = G(ModelX, list_a=2) # Many2Many can receive a number of instances to be created
assert len(instance_of_modelx.list_a.all()) == 2
instance_of_modelx = G(ModelX, list_a=[F(), F(), F()]) # Many2Many can receive a list of DynamicFixtures
assert len(instance_of_modelx.list_a.all()) == 3
a = G(ModelA)
instance_of_modelx = G(ModelX, list_a=[F(), a, F()]) # Many2Many can receive a list of instances
assert len(instance_of_modelx.list_a.all()) == 3
# You can pass arguments to F (DynamicFixture) recursively. This works for ForeignKey and ManyToMany Fields! Easy and customizable!
instance_of_modelx = G(ModelX, parent_left=F(other_text='wow', other_list=2))
assert len(instance_of_modelx.y_reference.other_list.all()) == 2
# Highly recursivable example:
# X has a ForeignKey to A
# A has a ForeignKey to B
# B has a ForeignKey to C
# this will create instances of C, B, A and X (in this order). Attribute d of C will be 'some value'
G(X, a=F(b=F(c=F(d='some value'))))
# for debug:
P(instance_of_modelx)
# Custom FileField:
class ModelX(models.Model):
my_file = models.FileField(upload_to='/')
from tempfile import mkstemp
pdf_a = File(open(mkstemp()[1], 'w'), name='a.pdf')
G(ModelX, my_file=pdf_a)
}}}
== Decorators ==
{{{
from django_dynamic_fixture.decorators import skip_for_database, only_for_database, SQLITE3
@only_for_database(SQLITE3)
def test_something1(self): pass
@skip_for_database(SQLITE3)
def test_something2(self): pass
@only_for_database("some value used in settings.DATABASES['default']['ENGINE']")
def test_something3(self): pass
@skip_for_database("some value used in settings.DATABASES['default']['ENGINE']")
def test_something4(self): pass
}}}
== Queries Module ==
{{{
python manage.py test --with-queries
python manage.py count_queries_on_save
}}}
=Information about the logic of the library=
==List of exceptions==
* UnsupportedFieldError: DynamicFixture does not support this field.
* InvalidConfigurationError: The specified configuration for the field can not be applied or it is bugged.
* InvalidManyToManyConfigurationError: M2M attribute configuration must be a number or a list of DynamicFixture or model instances.
* BadDataError: The data passed to a field has some problem (not unique or invalid) or a required attribute is in ignore list.
==DynamicFixture assume==
* if a field has a default value, it does not have unique=True.
* if a field has choices, it does not have unique=True.
* if there is a cyclic dependency, in some part the relationship must be nullable.
* if any of these requirements is a problem, you have to use customized values or override the behavior.
==DynamicFixture rules==
===General===
* The id (AutoField) is auto filled, unless you set a value to it.
* if a field has default value, it will be used by default.
* if a field has choices, it select each the first option by default.
* it fill nullable fields with data unless fill_nullable_fields is False.
* boolean fields will always receive False, unless it has default value.
* null boolean fields will always receive None, unless it has default value.
* Strings (CharField, Text, Url, Email...) and numbers (IntegerField, Float, Decimal...) are filled with a sequential and unique number for each test (1, '1', 2, '2'...). Each attribute has its own counter.
* You can override the behavior of the string and number fillers, if you want to.
===Custom Attributes===
* if it receive a customized data, it do not care about attributes null, unique, default or choices.
* if the specified fixture was bugged, it will raise an InvalidConfigurationError.
===Custom Fields===
* if it does not recognize the Field class, it will raise an UnsupportedFieldError.
* if a field is not default in Django, but it inherits from a Django field, it will be filled using its config.
* if a field is not default in Django and not related with a Django field, it will raise an UnsupportedFieldError.
* Customized data is also valid for unsupported fields.
===Related Objects===
* ForeignKey will be filled by default, considering unicity of data.
* It deal with cyclic dependencies, including self references (this avoid infinite recursion).
* By default, the fixture create just one cycle, but it is possible to specify more maps with number_of_laps parameter.
===Many to Many relationship===
* To add models in a m2m relation, the model must be persisted, so use the 'get' method.
* it expect to receive a parameter with the amount of instances that need to be created (using default configuration).
* Also, it can receive a list with DynamicFixture (F) or model instances (for custom items). The size of the list is the number of items that will be created.
* It works for default Many2Many and Many2Many with through.
===Ignoring fields===
* Useful when some fields need some calculation. For example, Django-MPTT models.
* Ignored fields are propagated ONLY to self references.
* Do not ignore required fields with 'get', only with 'new'. In other words, do not save an instance without a required field, unless you are expecting for an exception.
===Patterns===
* Use 'new' method for unit tests (not integration tests) for the main model.
* Use 'ignore_fields' option to deal with fields filled by listeners.
* Use custom values for unsupported fields.
* Use 'number_of_laps' option to test trees.
===Anti-Patterns===
* Use a auto generated data in an assertion method.
=Links of Comments=
* http://www.reddit.com/r/django/comments/fv1re/django_dynamic_fixture
* http://djangopackages.com/grids/g/fixtures/
* http://news.ycombinator.com/item?id=2275406
* http://pythonsmalltalk.blogspot.com/2011/02/django-dynamic-fixture.html
* http://pythonsmalltalk.blogspot.com/2011/03/django-dynamic-fixture-121.html
* http://pypi.python.org/pypi/django-dynamic-fixture/1.2
* http://code.activestate.com/pypm/django-dynamic-fixture
* http://groups.google.com/group/django-mptt-dev/browse_thread/thread/d9eb9e22ad4aa656
* http://groups.google.com/group/django-users/browse_thread/thread/1346a60008c21a7b
* http://groups.google.com/group/django-brasil/browse_thread/thread/757df09d3c3be81d
* http://linux.softpedia.com/get/Internet/HTTP-WWW-/django-dynamic-fixture-68711.shtml
=Change Log=
==Version 1.5.0==
* 2012/03/24 (yyyy/mm/dd)
* http://pypi.python.org/pypi/django-dynamic-fixture/1.5.0
* New features in DDF:
* global settings: DDF_DEFAULT_DATA_FIXTURE, DDF_FILL_NULLABLE_FIELDS, DDF_IGNORE_FIELDS, DDF_NUMBER_OF_LAPS, DDF_VALIDATE_MODELS
* new data fixture that generates random data
* new data fixture that use sequential numbers only for fields that have unique=True
* P function now accept a list of model instances
* Option to call model_instance.full_clean() validation method before saving the object (DDF_VALIDATE_MODELS).
* Validate field names. If a invalid field name is passed as argument, it will raise an InvalidConfigurationError exception.
* DateField options 'auto_add_now' and 'auto_add' are disabled if a custom value is used.
==Version 1.4.3==
* 2012/02/23 (yyyy/mm/dd)
* http://pypi.python.org/pypi/django-dynamic-fixture/1.4.3
* Bugfix in ForeignKeys with default values
==Version 1.4.2==
* 2011/11/07 (yyyy/mm/dd)
* http://pypi.python.org/pypi/django-dynamic-fixture/1.4.2
* Bugfix in FileSystemDjangoTestCase
==Version 1.4.1==
* 2011/11/07 (yyyy/mm/dd)
* http://pypi.python.org/pypi/django-dynamic-fixture/1.4.1
* New features in DDF:
* Now you can set a custom File to a FileField and the file will be saved in the file storage system.
* New features in FileSystemDjangoTestCase:
* create_django_file_using_file create a django.File using the content of your file
* create_django_file_with_temp_file now accepts a content attribute that will be saved in the generated file
* Bugfix in FileSystemDjangoTestCase:
* now create_django_file_with_temp_file close the generated file
==Version 1.4.0==
* 2011/10/29 (yyyy/mm/dd)
* http://pypi.python.org/pypi/django-dynamic-fixture/1.4.0
* New features:
* Nose plugin to count queries on each test
* Command line to count queries on the save (insert and update) of each model
* Bugfixes in DDF:
* Field with choice and default must use the default value, not the first choice value
* Validation if the class is a models.Model instance
* Showing all stack trace, when an exception occurs
* Bugfixes in decorators: default values of database engines were not used correctly
* Bugfixes in FileSystemDjangoTestCase tests
==Version 1.3.1==
* 2011/10/03 (yyyy/mm/dd)
* http://pypi.python.org/pypi/django-dynamic-fixture/1.3.1
* Bugfixes in FileSystemDjangoTestCase
==Version 1.3.0==
* 2011/10/03 (yyyy/mm/dd)
* http://pypi.python.org/pypi/django-dynamic-fixture/1.3.0
* New Feature: File System Django Test Case
* New Feature: Decorators skip_for_database and only_for_database
* Bugfix: Inheritance problems, before this version the DDF filled fields with the attribute parent_link
==Version 1.2.3==
* 2011/06/27 (yyyy/mm/dd)
* http://pypi.python.org/pypi/django-dynamic-fixture/1.2.3
* Bugfix in string truncation to max_length
==Version 1.2.2==
* 2011/05/05 (yyyy/mm/dd)
* http://pypi.python.org/pypi/django-dynamic-fixture/1.2.2
* Improvements in exception messages
==Version 1.2.1==
* 2011/03/11 (yyyy/mm/dd)
* http://pypi.python.org/pypi/django-dynamic-fixture/1.2.1
* Propagate ignored fields to self references
* Refactoring + Bug fixes
==Version 1.2==
* 2011/03/04 (yyyy/mm/dd)
* http://pypi.python.org/pypi/django-dynamic-fixture/1.2
* New Feature: ignore_fields
* New Feature: now it is possible to set the ID
==Version 1.1==
* Bug fixes
* http://pypi.python.org/pypi/django-dynamic-fixture/1.0 (1.0 has the 1.1 package)
==Version 1.0==
* Initial version
* Ready to use in big projects
= Testing =
* python manage.py test
* python manage.py test --with-coverage --cover-inclusive --cover-html --cover-package=django_dynamic_fixture.* --with-queries
= TODO List =
* auto config of denormalizated fields
* with_queries documentation and bugfixes (always print 0 queries)
* related_name documentation or workaround
* today, yesterday, tomorrow on fdf
* bugfix in fdf or ddf: some files/directories are not deleted
* tests with files in ddf
* tests with proxy models
* doc factory: example to generate models with validators in fields or in clean methods
* tests with GenericRelations, GenericForeignKey etc
* more tests with OneToOneField(parent_link=True)