Categories: Web Dev Training

One Easy Way To Speed up your Rails Tests and RSpec

There comes a time in the life of every Ruby on Rails project where you and your team will end up with long running tests. Rails tests can contain factories, fixtures and lots of setup procedures before tests are executed, and all of these can contribute to major slowness in the test runs.

I’ve seen four ways of dealing with slow running tests in Rails:

  1. start deleting tests (or mark them as skip-able): the drawback is your test coverage drops and you may end up with more bugs
  2. use more integration tests rather than unit tests: this exercises a lot of code paths so test coverage won’t drop too much but in the end most developers will write integration tests that exercise the “happy path”
  3. Run your tests in parallel
  4. Run only the tests that were most likely to be affected by recent code changes

The latter two methods are much better than the first two.

My favourite so far is #3 because it still runs all of the integration and unit tests that you have but makes use of the fact that you can offload the work of running tests to multiple machines. Everyone now has access to multiple machines through AWS (Amazon Web Services) or Microsoft Azure or RedHat’s cloud. You can even run tests in parallel on your local development machine.

Run Your Ruby on Rails Tests In Parallel

The idea is that each test file will be run in separate processes.

If you have 5 tests that have a duration 2 minutes, in sequential runs it will take 10 minutes to run the whole test suite. If you have 5 processes available for parallel runs, it will only take 2 minutes to run the whole test suite.

That’s a huge difference and means you can make 30 test runs in an hour rather than 6 test runs.

Splitting RSpec test files into multiple files

However, some of your Rails tests may take longer; within the spec you could have multiple test cases and contexts that are taking too long. For example, one test context with a few tests could be taking 1 minute while the rest of the test cases in that file only take 10 seconds. At that point, you can split the long-running test context into multiple files.

Here’s an example of how that might look like:

# spec/my_controller_spec.rb
describe MyController do
  context 'Slow tests' do
    it 'runs slowly #1' do
      # ...
    end
    it 'runs slowly #2' do
      # ...
    end
  end

  context 'Faster part of the test suite' do
    it 'runs in 10 seconds or less' do
      # ...
    end
  end
end

And now here’s how we could split that controller rspec test file into multiple files.

# spec/my_controller_spec.rb
describe MyController do
  context 'Faster part of the test suite' do
    it 'runs in 10 seconds or less' do
      # ...
    end
  end
end

# spec/my_controller_slow_1_spec.rb
describe :MyControllerSlow1 do
  def self.described_class
    MyController
  end

  include_context 'my controller helpers'

  it 'runs slowly #1' do
    # ...
  end
end

# spec/my_controller_slow_2_spec.rb
describe :MyControllerSlow2 do
  def self.described_class
    MyController
  end

  include_context 'my controller helpers'

  it 'runs slowly #2' do
    # ...
  end
end

The reason this works is because we override the class method described_class. This method is used by the rspec-rails extensions that make it easier to test Rails classes with RSpec.

By using shared contexts and helpers and by splitting files, you can optimize your Rails tests even further.

(If you liked this article, I have written about using mocks with Django and Python unit and integration testsĀ and using Protractor with AngularJS and how you can take screenshots with Selenium during test runs.)

Categories: Portfolio

Participated in a Hackathon: ArthritisHack 2017

On the weekend of October 13th to 15th, the #ArthritisHack hackathon took place at the Mars Discover District. It was a cool event and I haven’t attended a hackathon in ages. The last hackathon I attended was a hackathon sponsored by LinkedIn in the same place and before that it was a kind of catch-all hackathon with multiple APIs in the west end of Toronto where people used the Yellow Pages API and Soundcloud API.

At this event, with a team of five, we built a small automated marketing platform for arthritis-focused charity events and built a chatbot to engage people and raise awareness about arthritis.

Continue reading “Participated in a Hackathon: ArthritisHack 2017”