Multi-Engine Rails 3.2 Testing Tips & Tricks, Part 3

This is a continuation of my second post on setting up a CI server for a multi-engine rails 3.2 application.

Use `Pry.rescue {}` For Dynamic `binding.pry`

Getting access to an interactive REPL is essential when debugging a web application. Better Errors does a great job when when interacting with the app directly (in rails4 this functionality comes built in). binding.pry is a great tool when interacting with your code directly in your development or testing environment.

However, there are some cases where adding binding pry to just the right place is either painful or would require you to modify a external gem. An easy way to get around this is to use pry-rescue which will open a pry REPL wherever an exception occurs. This is especially helpful for debugging rake tasks.

Run Rails Server in Test Environment to Debug Hard-to-Replicate Issues

Sometimes I’ve run into issues that I can’t reproduce in development or staging. It’s been helpful to startup a rails server using the test environment to debug issues outside of the content of a specific spec:

bundle exec rails s -e test # if you have a test_app cd spec/dummy bundle exec rails s -e test Use Test Server Static Port Assignment for Absolute URL Dependent Functionality

If you use premailer with a CSS stylesheet, the external stylesheet reference must be absolute (at least, in the version of premailer the app is using).

Additionally, sometimes there is functionality which require the host name of the app to be set via a configuration preference (e.g. Spree Commerce with Spree::Config.set(:site_url, "domain.com")).

Capybara defaults to starting up a testing web server on a random port. This causes issues if you need to set a site wide configuration preference: you don’t know what the port is until the server is running.

I’ve found it helpful to set Capybara to use consistent port:

Capybara.server_port = 8081 Take a Screenshot of Feature Test State on Failure

Use capybara-screenshot to save a screenshot of what the page looked like that triggered the error. In addition to a PNG, a HTML file is also generated. I’ve found this to be very helpful in debugging feature tests.

# spec_helper.rb # disable by default Capybara::Screenshot.autosave_on_failure = false RSpec.configure do |c| c.before(:each, type: :feature) do Capybara::Screenshot.autosave_on_failure = example.metadata[:screenshot] end end

Check out this article for more information.

Increase Capybara Wait Time

In my testing enviornment I run all delayed jobs synchronously in order to test the results of backgrounded operations. This means that requests sometimes have to wait on slow external services or connections. Without increasing the default timeout setting, you’ll get errors from capybara:

Capybara.default_wait_time = 10 Nil Out User Generated Paper Clip File Upload References

Some of the seed data I extracted from the live application had paperclip attachment data. Here’s how to wipe it out quickly:

# seeds.rb Spree::Asset.update_all attachment_file_name: nil, attachment_content_type: nil, attachment_file_size: nil, attachment_width: nil, attachment_height: nil

If you need an image in place, set a default image:

# spec_helper.rb Spree::Image.attachment_definitions[:attachment][:default_url] = "http://placehold.it/460x260" Dotenv

If you have unit tests in your applications’ engines repositories, and you are using the 12 factor app structure, you are going to need to load the .env file from the parent directory.

# sub_engine/spec/spec_helper.rb if ENV['CIRCLECI'].nil? || ENV['CIRCLECI'] != 'true' require 'dotenv' Dotenv.load! '../.env' end

Continue Reading

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

Continue Reading