Hi Josh,

Fixtures don't receive a lot of attention because they're hard to maintain and 
generally inferior to object generators such as factory_boy. Still, it would be 
good to optimize them.

On 7 juin 2014, at 09:34, Josh Smeaton <[email protected]> wrote:

> I've been looking into the django testing infrastructure today to see if 
> there was any particular reason why the test suite takes so long to run.

You aren't the first one to notice the overhead of fixtures: 
https://code.djangoproject.com/ticket/9449.

That ticket focuses on the cost of parsing fixtures, not loading them.

> Note that the above isn't exactly right, but I think it demonstrates the 
> problem. Each test_method is given its own TestCase (unnecessary python 
> overhead)
> but more importantly, we're not using transactions to get back to the initial 
> data. We're using transactions to get back to an empty database before 
> loading fixtures again.

I have a theory for this. Until Django 1.6, Django didn't have support for 
savepoints. All you could do is a full rollback.

So you had a choice between:

- Load fixtures
- For each test method
        - Start transaction
        - Run test
        - Roll back transaction
- Truncate tables (that's awfully slow when you have lots of models, like 
Django's test suite does)

or:

- For each test method
        - Start transaction
        - Load fixtures
        - Run test
        - Roll back transaction

The second solution is /probably/ faster for /some/ use cases, and certainly 
for Django's own test suite.

It may also explain why Django rewraps each method in a test case, but I'm not 
sure about that part.

Now, if the test suite is running on a database that supports savepoints 
(there's a database feature providing this information) you could do:

- Start transaction
- Load fixtures
- For each test method
        - Create savepoint
        - Run test
        - Roll back to savepoint
- Roll back transaction

> I know lots of people have invested lots of time on the test suite, 
> especially when it comes to run time. I doubt that I'm raising anything new 
> for the people who have come before. But my question is why? Is there a 
> reason that each test method has to have its own TestCase? Is there a reason 
> that each test method has to load its own fixtures again and again, or is 
> that just a symptom of how each test_method is collected by the test suite?

I don't have all the answers, but hopefully the above sheds some light on the 
underlying issues.

> There are many kinds of tests that deal with the ORM that should be able to 
> rely on fixtures being loaded once for the entire TestCase, and relying on 
> transactions to get back to initial data. Is this theoretically possible, or 
> am I missing something? I figure we could eliminate something like 1/3rd of 
> all queries.

That would be pretty cool. 

If you work on a patch, please keep multiple databases in mind -- I don't know 
how they're handled transaction-wise.

-- 
Aymeric.

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/8BE3B804-C9EF-4D0B-A5B3-E9A66F7EC4CF%40polytechnique.org.
For more options, visit https://groups.google.com/d/optout.

Reply via email to