Re: Test fixtures loaded ~100 times faster by overwriting BaseDatabaseCreation.create_test_db + question

2010-01-15 Thread Matt Schinckel
On Jan 14, 11:07 pm, Russell Keith-Magee 
wrote:
> On Thu, Jan 14, 2010 at 4:43 PM, Piotr Czachur  wrote:
> > Guys,
> > I was really unhappy to see how slow fixtures are loaded before every
> > test. I'm not talking about initial_data stuff that is loaded just in
> > beginning, and then reset by rollback. Fixtures used for unit tests
> > are loaded on demand (fixtures = [f1, f2]), and this is really slow,
> > because thousands of SQL queries going to database (SELECTs, SELECTs,
> > INSERTs).
> > For my small test suite (130 tests) and small fixtures (15 items) I've
> > recorded ~16000 queries to database - I was really blown away by this
> > number. 99% of this queries was related to fixtures loading.
>
> We are well aware of the speed problems associated with fixture setup
> and teardown during testing. We're open to any practical suggestions
> on how to speed them up.
>

I came across some similar issues with an Event/Occurrence pair of
models (each Event has one or more occurrences, representing the
potentially repeating nature of the event).  Because an Event could
have many thousand Occurrences, and modifying the Event may require
modifying, or even recreating all of the Occurrences, I looked at some
ways to improve performance.

Because we have a series of homogenous object types, we can combine
all of the SQL queries into one. I wonder if something similar could
be done with fixtures: create all of the objects, but instead of
saving them one at a time, save them in one batch.  I hand coded the
query, as this was a development exercise, and wasn't for production.

This would probably require significant thought as to the best way to
do this: perhaps a create_many() method on the Manager might be a
better solution?

I think I'll have another look at this - I'm about to revisit that
code anyway.

Any other suggestions are welcome, too :)

>
> As I said, we're more than happy to look at any proposal to improve
> the speed of testing in Django, but those changes can't come at the
> cost of fundamentally changing what it means to write a test.

Agreed. I use the different fixtures in test classes to have a known
state at the beginning of each test, that varies across test cases.

Matt.
-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-us...@googlegroups.com.
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en.




Re: Test fixtures loaded ~100 times faster by overwriting BaseDatabaseCreation.create_test_db + question

2010-01-14 Thread Russell Keith-Magee
On Thu, Jan 14, 2010 at 4:43 PM, Piotr Czachur  wrote:
> Guys,
> I was really unhappy to see how slow fixtures are loaded before every
> test. I'm not talking about initial_data stuff that is loaded just in
> beginning, and then reset by rollback. Fixtures used for unit tests
> are loaded on demand (fixtures = [f1, f2]), and this is really slow,
> because thousands of SQL queries going to database (SELECTs, SELECTs,
> INSERTs).
> For my small test suite (130 tests) and small fixtures (15 items) I've
> recorded ~16000 queries to database - I was really blown away by this
> number. 99% of this queries was related to fixtures loading.

We are well aware of the speed problems associated with fixture setup
and teardown during testing. We're open to any practical suggestions
on how to speed them up.

> So I came to conclusion that I can load my all fixtures just after
> initial_data fixtures are loaded at beginning, so database rollback
> can be used by Django test infrastructure to reset database state in a
> fraction of second.

This might work for your particular test suite, but it isn't that
simple in the general case. More details in a moment.

> Question:
> Like you see I decorated and overwrote create_test_db, but what I
> don't like here is that I had to add "setup_environ(settings)" to
> prevent getting exception, because Django was not initialized at this
> moment.
> execute_manager(settings) also runs setup_environ(settings) so it is
> run twice.
> Is there a better place/time to execute such overwriting? ...because I
> see this little tricky.

Yes - rather than dynamically monkeypatching, write a custom test
runner [1] that calls into your customized create/destroy routines.

[1] http://docs.djangoproject.com/en/dev/topics/testing/#defining-a-test-runner

> P.S.
> The side effect was that I have to remove all "fixture = [a,b,c]" from
> my tests, because I have all fixtures loaded at beginning before tests
> are run - but I cannot see this as a problem.

This is a little more than a 'side effect' - it's a fundamental change
to the expectations of test cases. The major reason to use fixture=[]
notation is to allow every test case to have it's own test fixtures.

This isn't just a good idea - it's a fundamental requirement for
certain types of tests. For example, consider a simple suite with two
tests that validate that an article list displays correctly. The first
test validates that the list displays when articles are defined; the
second test validates that error text is displayed when no articles
are defined. The test fixture requirements for the two tests cannot be
accommodated in a single set of suite-wide test fixtures.

As I said, we're more than happy to look at any proposal to improve
the speed of testing in Django, but those changes can't come at the
cost of fundamentally changing what it means to write a test.

Yours,
Russ Magee %-)
-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-us...@googlegroups.com.
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en.