Automated Tests on Multi-Engine Rails 3.2 App, Part 2

This is a continuation of my first post on automated testing a large rails app.

Setting up the Continuous Integration Server Configuration

In most cases your CI server setup is pretty trivial, some aspects of the apps setup made it a little more challenging:

  • I use submodules that reference private repositories
  • The engines that make up the app have their own unit tests
  • All of the engines depended on Spree Commerce, which meant they needed to run test_app to execute properly
  • There were a couple custom rake tasks I needed to run before running tests
checkout:
  post:
    - git submodule sync
    - git submodule update --init
dependencies:
  post:
    - cd engine1; bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3
    - cd engine2; bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3
database:
  post:
    - bundle exec rake db:seed app:custom1 app:custom2
test:
  pre:
    - cd engine1 && bundle exec rake test_app
    - cd engine2 && bundle exec rake test_app
  override:
    - cd engine1 && bundle exec rspec
    - cd engine2 && bundle exec rspec
    - bundle exec rspec

minimize external system dependencies

Toggle Between Selenium and WebKit

Selenium helps me code & debug feature tests by letting me open up binding.pry in the test and interact with a Firefox instance. WebKit executes tests much faster.

I wanted both, and wanted the ability to switch between the two easily.

Here’s the Gemfile:

group :test do
  gem 'capybara', '~> 2.2.1'
  gem 'capybara-screenshot', "~> 0.3.17"
  gem "selenium-webdriver", '~> 2.44.0'
  gem "capybara-webkit"
end

Here’s the rspec snippet you’ll need to load in spec_helper.rb:

RSpec.configure do |c|
  c.before(:each, type: :feature) do
    Capybara::Screenshot.autosave_on_failure = example.metadata[:screenshot]

    if example.metadata[:selenium].present? || ENV["SELENIUM"] == "true"
      Capybara.current_driver = :selenium_firefox_driver
    else
      Capybara.current_driver = :webkit
    end
  end
end

# Register the selenium firefox driver
Capybara.register_driver :selenium_firefox_driver do |app|
  profile = Selenium::WebDriver::Firefox::Profile.new
  Capybara::Selenium::Driver.new(app, :browser => :firefox, :profile => profile)
end

To run the tests with selenium just set the ENV var:

export SELENIUM=true

Or, better yet, use dotenv and put in .env.

If you used cask to install Firefox you’ll need the following snippet:

firefox_cask_path = '/opt/homebrew-cask/Caskroom/firefox/latest/Firefox.app/Contents/MacOS/firefox-bin'

if File.exists?(firefox_cask_path)
  Selenium::WebDriver::Firefox::Binary.path = firefox_cask_path
end

Conditionally Raise Exceptions in Tests

By default the test environment does not raise exceptions. When something goes wrong, you don’t get a stack trace. I wanted to toggle this functionality to debug tests; here’s what I did:

# config/environments/test.rb

config.action_dispatch.show_exceptions = ENV['RAISE_EXCEPTIONS'] == "true"

Output Current File and Line when Running RSpec Tests

Originally pulled from this StackOverflow post:

RSpec.configure do |c|
  c.before(:each, js: true) do |s|
    md = s.example.metadata
    x = md[:example_group]
    puts "=> #{x[:file_path]}:#{x[:line_number]} #{md[:description_args]}"
  end
end