@load_fixture annotation for test cases.

89 views
Skip to first unread message

Matteo Kloiber

unread,
Sep 2, 2014, 2:34:17 PM9/2/14
to django-d...@googlegroups.com
Hello,
I thought it might be pretty helpful if there was a load_fixtures annotation that loads fixture for a specific test method in TransactionTestCase. On some occasions, it might be pretty hard to test a model/view that uses only one or a few fixtures that are always the same. Here are some occasions, where it might be helpful to have these annotation. 

 - I may want to test when the database is empty.
 - It might be necessary to have a fixture with a lot of data (and I mean >1000). Loading some much data for every testcase is highly ineffective because it takes a time to clean up and load the data again.

I’m sure there are more occasions when this might be helpful.
Here is what the implementation might look like:
@load_fixtures(*fixtures, flush=False)
fixtures are the fixtures to load (just like the instance variable). flush means whether the old data (i.e. the data that was loaded by the instance variable) should be flushed. `fixtures` should be optional so that flush can sand-alone. That allows me to have an empty database (this could be useful when only a very limited amount of tests need an empty database while the other tests need the default fixtures). 
It shouldn’t replace the fixtures instance variable, it should just be an addition. 

I know, it can be implemented and doesn’t require changes in the core but it would be super helpful if it came out if the box. The flush parameter could be optimized when implementing directly in the core (i.e. TransactionTestCase). Loading default fixtures (the ones defined in TestCase.fixture) could be prevented this way and the tests might even run a bit quicker. This is quicker than flushing the database/rolling back all changes.

Sincerely,
Matteo Kloiber

Josh Smeaton

unread,
Sep 2, 2014, 6:27:53 PM9/2/14
to django-d...@googlegroups.com
The idea isn't bad, except that the performance of fixture loading is pretty terrible in general. Take a look at ticket https://code.djangoproject.com/ticket/20392 for some performance profiling and discussion.

As far as I'm concerned, using fixtures is the wrong way to populate data for tests. You're much better off creating the objects you need for each test within the test, or creating them directly inside the setUp method. You avoid the parsing and loading of json data, which is quite substantial!

You could also use a third party app like factory boy to generate the data you need for each test. I think we should be encouraging this kind of design a lot more, rather than trying to optimise or push fixture loading in general.

Regards,

Josh

Matteo Kloiber

unread,
Sep 5, 2014, 9:27:59 AM9/5/14
to django-d...@googlegroups.com
Hey Josh,
Thanks for the answer, I'll give the factory boy a shot. I just don't like to put code that populate fields in the setup function (especially when using nested relations). It's just a lot of code to achieve it and lost time to me. (I normally use the current test database and dump relevant data (and sometimes remove some)). That is way more quicker than creating user, user profile, and whatsoever I need to actually test my model/view. I also only run just the unit tests I need, which is most of the time less than 30. I just run all when I'm done and want to commit my changes or I'll let Jenkins worry about that (and I really don't care if jenkins takes 5 or 15 minutes, although I do see the point for really big projects). 

Shai Berger

unread,
Sep 5, 2014, 4:53:26 PM9/5/14
to django-d...@googlegroups.com
On Tuesday 02 September 2014 15:27:53 Josh Smeaton wrote:
>
> As far as I'm concerned, using fixtures is the wrong way to populate data
> for tests. You're much better off creating the objects you need for each
> test within the test, or creating them directly inside the setUp method.

+1.

> You avoid the parsing and loading of json data, which is quite substantial!

This I find a rather weak argument. The main reason to create test-objects in
code rather than fixtures is that models evolve (especially when thinking about
Django>=1.7), and fixtures are pretty close to impossible to adapt. I've been
involved in efforts to do the automatic adaptations (essentially, start with an
empty DB and code at the commit before the change; load the fixture, update
sources, migrate, and dump the new fixture). There are significant problems with
this approach (e.g. if the code that does this sits in the same repo as the
project code, then fixes to some parts of it need to be added with a time
machine).

HTH,
Shai.

Reply all
Reply to author
Forward
0 new messages