Rails 5.2 Parallel Tests with RSpec for local and Travis

in #rails6 years ago (edited)

new-brain-chip-light-blazingly-fast-1.jpg

In order to make our test suite faster, different approaches have been tried:

  • parallelize on one VM using parallel_tests gem
  • parallelize on mutliple VMs (2) using knapsack gem and matrix with parallel_tests

Regarding the approach using 2 VMs we have system dependencies to install (before_install) with symbolic links which cannot be cached and instantiating 2 VMs to run tests in parallel actually doubles the total time because of that. Also if one job is already taken then the whole test suite will have to wait for that job to complete before starting the next.

While Rails 6 will bring parallel testing, here is how to implement it for Rails 5.2, RSpec and for local and TravisCI.

Install

group :development, :test do
  gem: parallel_tests
end

Database configuration

Append the environment variable TEST_ENV_NUMBER to the test database name in database.yml

default: &default
  adapter: postgresql
  encoding: unicode
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 8 } %>
test:
  <<: *default
  url: <%= "#{ENV.fetch('DATABASE_URL')}/#{ENV.fetch('DATABASE_NAME')}#{ENV.fetch('TEST_ENV_NUMBER')}" %>

or

test:
  <<: *default
  database: <%= ENV.fetch('DATABASE_NAME') %><%= ENV['TEST_ENV_NUMBER'] %>
  username: ENV['DATABASE_USER']
  password: ENV['DATABASE_PASSWORD']
  host: ENV['DATABASE_HOST']
  port: ENV['DATABASE_PORT']

Create the test databases

One test database is used per thread with the name set previously in the database configuration with the TEST_ENV_NUMBER variable.
parallel_tests will use the number of CPU available by default (including virtual) and this can be overridden.

Run

bundle exec rake parallel:create

override:

bundle exec rake parallel:create[2]

Run RSpec

bundle exec rake parallel:spec

override:

bundle exec rake parallel:spec[2]

Using binstubs

use binstubs to use spring loader for faster tests.
Patch spring to reconnect the database and then force-enabled it by running with DISABLE_SPRING=0

spring configuration

Create config/spring.rb and add

require 'spring/application'
class Spring::Application
  alias connect_database_orig connect_database
  def connect_database
    disconnect_database
    reconfigure_database
    connect_database_orig
end
  def reconfigure_database
    if active_record_configured?
      ActiveRecord::Base.configurations =
        Rails.application.config.database_configuration
    end
  end
end

source: https://github.com/grosser/parallel_tests/wiki/Spring

Run

./bin/rake parallel:spec

Using the command line interface

parallel_rspec spec -n 12

Travis CI

env:
  - RAILS_ENV=test
script:
  - ./bin/rake db:schema:load
  - ./bin/rake parallel:create
  - ./bin/rake parallel:spec

Results

Number of rspec tests: 876

StrategyNumber of processesCommandFinished in
RSpec1bundle exec rspec2 minutes 2 seconds (122 seconds)
Parallelizing2 processesbundle exec rake parallel:spec[2]1 minute 24 seconds (84 seconds)
Parallelizing6 processesbundle exec rake parallel:spec[6]44 seconds
Parallelizing12 processesbundle exec rake parallel:spec[12]49 seconds
Parallelizing with spring2 processes./bin/rake parallel:spec[2]75 seconds
Parallelizing with spring6 processes./bin/rake parallel:spec[6]42 seconds
Parallelizing with spring12 processes./bin/rake parallel:spec35 seconds
Sort:  

Congratulations @davidalphen! You received a personal award!

Happy Birthday! - You are on the Steem blockchain for 1 year!

You can view your badges on your Steem Board and compare to others on the Steem Ranking

Do not miss the last post from @steemitboard:

The new SteemFest⁴ badge is ready
Vote for @Steemitboard as a witness to get one more award and increased upvotes!

Coin Marketplace

STEEM 0.20
TRX 0.14
JST 0.030
BTC 68147.96
ETH 3273.79
USDT 1.00
SBD 2.66