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 --full
orrails 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
gemspec
file:s.add_development_dependency 'rspec-rails' s.add_development_dependency 'capybara' s.add_development_dependency 'factory_girl_rails'
-
Add this line to your
gemspec
file:s.test_files = Dir["spec/**/*"]
-
Modify
Rakefile
to 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 => :spec
This will setup your
Rakefile
to 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.rb
file: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" end
This 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 end
Here, we're telling Rails when generating models, controllers, etc. for your engine to use RSpec and FactoryGirl, instead of the default of
Test::Unit
and fixtures
After this, you can start writing specs with FactoryGirl factories and integration specs (inside the spec/features
directory) with Capybara. Have fun testing!