ANN: faster fixtures (or how to spend less time loading fixt

Short version:
Before:
Finished in 192.609637 seconds.
183 tests, 5100 assertions, 0 failures, 0 errors

After:
Finished in 104.491294 seconds.
183 tests, 5100 assertions, 0 failures, 0 errors

Ok, so this app does have a lot of big fixtures but we’ve seen decent
gains on all our apps (typically 30-40%)

The long version:
fixtures are loaded once per testcase. If every single of your tests
names 0 or 1 fixtures than that’s fine. Back in the real world, customer
has_many :orders, :complaints, orders has_many :products etc… the
tests for all of orders, complaints, products, customer probably name
all those fixtures.

If a model uses another that isn’t named in the fixtures you can get
weird failures (because the table won’t have been cleared out and had
fresh data stuck in it prior to running the test, so for reasons of
maintainability we’ve ended up with all our fixtures in test_helper.
This of course means that if you have 50 unit tests, each one is being
loaded 50 times, i.e. 49 times too many. With some small caveats, this
plugin addresses this situation

Caveats:

  • this is an all or nothing thing: you can’t have it on for some
    testcases, off for others
  • all of your fixtures must be named in test_helper
  • time stops (is stubbed out)i.e :
    now = Time.now
    get :index
    assert Time.now > now

will fail. the point at which time stops is just before fixtures are
loaded

Setting up:

  • make sure you have mocha (gem install mocha)
  • grab the plugin from
    NameBright - Coming Soon
  • make sure all your fixtures must be named in test_helper
  • add require ‘faster_fixtures’ to your test_helper

Run tests and enjoy!

For another solution to this (but which means you can’t use the fixtures
accessors (eg foos(:first_foo) see this)

Thoughts, comments, suggestions etc… appreciated as usual. It works
great for all our apps, but I’d love to hear about it if it breaks yours
(and hopefully fix it :slight_smile: )

Fred

I’ve just updated this to remove the requirement that all your fixtures
be in test_helper.rb. You can now declare them whenever, whereever you
want and my plugin just insures that any given fixture is not loaded
more that once.
I’d love to know if this works for other people (or indeed if it
doesn’t!)

Fred

Frederick C. wrote:

I’ve just updated this to remove the requirement that all your fixtures
be in test_helper.rb. You can now declare them whenever, whereever you
want and my plugin just insures that any given fixture is not loaded
more that once.
I’d love to know if this works for other people (or indeed if it
doesn’t!)

Fred

Slick stuff – a test suite that ran in 50 seconds now runs in 28
seconds.

Once issue I’ve run across – I’ve got some unit tests in a
sub-directory under /test/unit/, and they aren’t able to access any
fixture data when I run the suite with faster_fixtures required. When I
run the tests individually, they can access fixture data just fine.

I’ve tried to reproduce this but couldn’t. Could you give some more
details about your setup and the errors you’re getting ?

Thanks,

Fred

Geoff Buesing wrote:

Slick stuff – a test suite that ran in 50 seconds now runs in 28
seconds.

Once issue I’ve run across – I’ve got some unit tests in a
sub-directory under /test/unit/, and they aren’t able to access any
fixture data when I run the suite with faster_fixtures required. When I
run the tests individually, they can access fixture data just fine.

Interesting - I’ll have a look.

Fred

For a clearer explanation of what’s going on, see

Fred

Frederick C. wrote:

I’ve tried to reproduce this but couldn’t. Could you give some more
details about your setup and the errors you’re getting ?

Thanks,

Fred

Fred,

Thanks for following up on this.

I created a fresh Rails app to try to reproduce this bug, but
(consistent with your findings) I wasn’t able to.

I did figure out a workaround – I’m using test/spec for my tests; when
I change the problem test (the one in a subdirectory of
RAILS_ROOT/test/unit) to standard test/unit style, it passes fine. Who
knows why.

My setup: Ruby 1.8.6, a recent version of edge Rails, with
test_spec_on_rails and fixture_references plugins (plus some other
common plugins that shouldn’t be interfering with testing.)

The problem is only with one particular record in one particular YAML
fixture file (which looks to be in fine YAML form) – I get
“ActiveRecord::RecordNotFound: Couldn’t find Location with ID=1” when I
run the suite, but when I run the individual test, it runs just fine.
When I check the db after I run the suite, I find three records in the
corresponding table; after I run the individual test, I see four.

And if I don’t require ‘faster_fixtures’ in my test.rb, I have no
problem.

So, who knows…?

Geoff