Inheriting a legacy application doesn't really have to be a chore. Bringing everything up to date is rewarding in its own way, although writing a ton of new tests isn't the most exciting thing around.
Once everything was at a point we were comfortable with, we replaced the tightly coupled fixtures with Factory Girl. I knew there's a significant performance penalty to be paid, but it was rather shocking. At 20 minutes, the test suite took almost twice as long.
I refactored some tests, mostly replacing FactoryGirl's create method with build_stubbed for non database operations but managed to shave off only two minutes.
After some research, it looked like a user was created for every controller spec. There were legitimate cases, but most of the time this wasn't the case. So I ended up doing the following - a controller's current_user method gets stubbed by default, whereas if a current_user argument is passed it gets created as an AR object, for instance:
it "does stuff", current_user: true do
# doing stuff
end
The code responsible looked similar to the following:
RSpec.configure do |config|
config.before :each, type: :controller do
user = if example.options[:current_user]
FactoryGirl.create(:user)
else
FactoryGirl.build_stubbed(:user)
end
controller.stub(:current_user).and_return(user)
end
end
The tests were faster at almost 12 minutes, but they still felt slow. Rspec's "--profile" flag didn't return any major offenders and just confirmed that most of the tests were just "slow". Trying to shave a few more seconds, I tried to use the same current_user approach to restrict search indexing.
As we were using an acts_as_solr:
RSpec.configure do |config|
config.before :each do
solr_models = [Model1, Model2, #..]
solr_models.each do |model|
if example.options[:search]
ActsAsSolr::Post.execute(Solr::Request::Delete.new(:query => "type_t:#{model}"))
model.configuration[:if] = true
else
model.configuration[:if] = false
end
end
end
end
Not the cleanest implementation around, but it got the job done. The results were surprising to say the least. The tests took almost two and a half minutes, which is quite ok for over one thousand tests.