A long time ago (django 1.3 era) I wrote a library (no need to change
django) to do exactly this, using savepoints to rollback:
https://github.com/machinalis/django-fasttest
It worked pretty well for a large project and provided a large speedup (i
think it was about 5x) on a large test suite. But I haven't mantained it
since, I started doing everything with factories (factory boy) and
abandoning fixtures because they were hard to maintain. You might find it
useful if you can update it to newer django versions; also note that the
current code was developend with postgres, it might work on some other db
but I have no idea.
Regards,
D.
On Sat, Jun 7, 2014 at 4:34 AM, 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.
> Mainly, I didn't understand why fixtures are loaded for every single test
> method. To be honest, I didn't think fixtures were loaded for every test
> method; I assumed they were loaded once when the TestCase was created.
>
> My mental model looked like this:
>
> # for each test module:
> call_command(flush) # flush the DB ready for this test case
> testcase = get_test_case() # returns the next subclass of TestCase (or
> TransactionTestCase etc)
> *testcase.load_fixtures() # populate the DB with data for the entire test
> case*
> for test_method in testcase.get_test_methods():
> with db.transaction(): # at the end of each test_method, rollback so
> that we're back to our fixtures
> testcase.setUp()
> getattr(testcase, test_method)()
> testcase.tearDown()
>
>
> Unfortunately, that's not at all what happens. For each test method,
> you're given a brand new instance of the testcase, and the initial data is
> loaded again:
>
> # for each test module:
> call_command(flush) # flush the DB ready for this test case
> testcaseclass = get_test_case()
> for test_method in testcaseclass.get_test_methods():
> with db.transaction(): # at the end of each test_method, rollback to
> an empty database
> testcase = testcaseclass(testMethod=test_method)
> *testcase.load_fixtures() # populate the DB with data for a
> single test_method*
> testcase.setUp()
> testcase.run() # runs the testMethod
> testcase.tearDown()
>
>
> 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 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?
>
> 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.
>
> Regards,
>
> Josh
>
> --
> 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/07c8e766-43e6-4362-bba1-695d3855a77a%40googlegroups.com
> <https://groups.google.com/d/msgid/django-developers/07c8e766-43e6-4362-bba1-695d3855a77a%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
> For more options, visit https://groups.google.com/d/optout.
>
--
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/CALuYSZX78Hp_Pcr-WUtFNTXHzj95T6AZ-XvQOfwDvaMpNV6d_g%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.