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
Strategy | Number of processes | Command | Finished in |
---|---|---|---|
RSpec | 1 | bundle exec rspec | 2 minutes 2 seconds (122 seconds) |
Parallelizing | 2 processes | bundle exec rake parallel:spec[2] | 1 minute 24 seconds (84 seconds) |
Parallelizing | 6 processes | bundle exec rake parallel:spec[6] | 44 seconds |
Parallelizing | 12 processes | bundle exec rake parallel:spec[12] | 49 seconds |
Parallelizing with spring | 2 processes | ./bin/rake parallel:spec[2] | 75 seconds |
Parallelizing with spring | 6 processes | ./bin/rake parallel:spec[6] | 42 seconds |
Parallelizing with spring | 12 processes | ./bin/rake parallel:spec | 35 seconds |
Congratulations @davidalphen! You received a personal award!
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:
Vote for @Steemitboard as a witness to get one more award and increased upvotes!
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit