Rails Engine Testing with RSpec, Capybara, and FactoryGirl
Brian Landau, Former Developer
Article Category:
Posted on
UPDATED: I've updated the instructions based on feedback in the comments suggesting the use of the --dummy-path=spec/dummy --skip-test-unit options on the rails plugin new command.
Recently, we've been doing a lot more with Rails engines. We've developed a few engines that we've released publicly, and even more that we use privately on applications. We've found it's a good way to organize and share reusable code across a number of applications.
We really like using RSpec, Capybara, and FactoryGirl to test our Rails applications, and we like to use them to test our engines too. Here's a few steps to get your new engine up and running with these gems in no time:
- Run
rails plugin new ENGINE_NAME --dummy-path=spec/dummy --skip-test-unit --fullorrails plugin new ENGINE_NAME --dummy-path=spec/dummy --skip-test-unit --mountable. This is a good discussion of why you'd choose mountable or full engines. -
Add these lines to the
gemspecfile:s.add_development_dependency 'rspec-rails' s.add_development_dependency 'capybara' s.add_development_dependency 'factory_girl_rails' -
Add this line to your
gemspecfile:s.test_files = Dir["spec/**/*"] -
Modify
Rakefileto look like this:#!/usr/bin/env rake begin require 'bundler/setup' rescue LoadError puts 'You must `gem install bundler` and `bundle install` to run rake tasks' end APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__) load 'rails/tasks/engine.rake' Bundler::GemHelper.install_tasks Dir[File.join(File.dirname(__FILE__), 'tasks/**/*.rake')].each {|f| load f } require 'rspec/core' require 'rspec/core/rake_task' desc "Run all specs in spec directory (excluding plugin specs)" RSpec::Core::RakeTask.new(:spec => 'app:db:test:prepare') task :default => :specThis will setup your
Rakefileto run your specs and make that the default task. It will also setup the specs to reload the test database just like how it works inside a Rails application. -
Create a
spec/spec_helper.rbfile:ENV['RAILS_ENV'] ||= 'test' require File.expand_path("../dummy/config/environment.rb", __FILE__) require 'rspec/rails' require 'rspec/autorun' require 'factory_girl_rails' Rails.backtrace_cleaner.remove_silencers! # Load support files Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f } RSpec.configure do |config| config.mock_with :rspec config.use_transactional_fixtures = true config.infer_base_class_for_anonymous_controllers = false config.order = "random" endThis code requires all the gems you need for writing your specs, loads the dummy application, and configures RSpec.
-
Finally, add this config to your engine file (lives at
lib/my_engine/engine.rb):module MyEngine class Engine < ::Rails::Engine config.generators do |g| g.test_framework :rspec, :fixture => false g.fixture_replacement :factory_girl, :dir => 'spec/factories' g.assets false g.helper false end end endHere, we're telling Rails when generating models, controllers, etc. for your engine to use RSpec and FactoryGirl, instead of the default of
Test::Unitand fixtures
After this, you can start writing specs with FactoryGirl factories and integration specs (inside the spec/features directory) with Capybara. Have fun testing!