I am on a quest to make my Rails tests faster. I only have 520 tests,
but they take 62 seconds to run in bash, and 82 seconds to run in
Rubymine.

As an example of a typical controller test, I was using this code to
sign_in as a @user and create the basic @comment in a
CommentsController for my RSpec controller tests:

    before(:each) do
      @user = Factory.create(:user)
      sign_in @user

      @comment = Factory.create(:comment)
    end

As you might realize... this is slow. It builds a `@user`, but also
builds the associations for that user. Same for the `@comment`.

So I thought calling `Factory.build(:user)` would solve it... but I
get weird errors. For example, `current_user` returns `nil`.

So... I decided to use `Factory.build()` and stub out all the before
filters in my parent controller. However, my rspec log still says a
TON of inserts are hitting the database when I inspect the RSPec log
afterwards (we are talking hundreds of lines of code for just 3
tests!)

      before(:each) do
        @user = Factory.build(:user)
        #sign_in @user

        controller.stub(:authenticate_user!) #before_filter
        controller.stub(:add_secure_model_data) #before_filter
        controller.stub(:current_user).and_return(@user)

        @comment = Factory.build(:comment)
      end

The sad fact is, the above `before(:each)` block has ZERO effect on
test performance. As I discovered, calling `Factory.build()` will
still internally call `Factory.create()` on the child associations.

Here is a `before(:each)` block that effectively removes the junk
produced in the RSpec log. It gave me a 35-40% test performance boost

      before(:each) do
        @user = Factory.build(:user, :role => Factory.build(:role))
        #sign_in @user

        controller.stub(:authenticate_user!)
        controller.stub(:add_secure_model_data)
        controller.stub(:current_user).and_return(@user)

        @site_update = Factory.build(:site_update, :id => 5, :author
=> Factory.build(:user, :role => Factory.build(:role)))

        @comment = Factory.build(:comment,
                                 :author => Factory.build(:user, :role
=> Factory.build(:role)),
                                 :commentable => @site_update)
      end

This makes the tests run faster, but it's also ugly as sin. We can't
seriously write this for every test... do we? That's nuts. I'm not
doing it.

I also want to point out that any one of these `Factory.build()` lines
still takes about .15 seconds even though they are NOT hitting the
database!

Running only 3 tests still results in about .3 to .35 seconds of time
taken up by factory_girl PER test! I think that is totally
unacceptable. If you remove the `Factory.build()` lines, the tests run
in 0.00001 seconds.

I think the jury is in: factory_girl is one really slow library. Is
the only solution to not use it?

-- 
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Talk" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/rubyonrails-talk?hl=en.

Reply via email to