My Rails Testing Setup
- development
- rails
- 1040 words
The purpose of this article is a step-by-step guide to get up and running with my preferred rails testing workflow (against rails 5.0.1
/rspec 5.3
).
It could most likely become an application template as it’s mostly just copying and pasting.
This mostly covers testing, but other things will doubtless slip through.
rails new $app_path --database mysql --skip-bundle --skip-test
cd $app_path
At this point, I tend to tidy up the Gemfile
somewhat and remove any Gems I’m not going to use.
Then replace the groups at the end with something like this:
group :development do
gem 'spring'
gem 'spring-commands-rspec'
gem 'capistrano-rails'
gem 'guard'
gem 'guard-rails'
gem 'guard-rspec'
gem 'rubocop', require: false
gem 'reek', require: false
end
group :development, :test do
gem 'byebug', platform: :mri
gem 'rspec-rails', '~> 3.5'
gem 'rspec-mocks'
gem 'capybara'
gem 'poltergeist'
gem 'forgery'
gem 'factory_girl_rails'
gem 'seedbank'
end
group :test do
gem 'database_cleaner'
gem 'simplecov', require: false
end
Let’s install everything:
bundle install
rails generate rspec:install
mkdir spec/support
Now we need to tell rspec
about the various other tools we’ll be using during test runs.
First, we’ll add the following to the top of spec/rails_helper.rb
:
ENV['RAILS_ENV'] ||= 'test'
if ENV['RAILS_ENV'] == 'test'
require 'simplecov'
SimpleCov.start 'rails'
end
And the following line after the require 'rspec/rails'
line:
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
Each of the following files will be loaded by the above, and should be placed
in the newly created spec/support
- with contents roughly as follows:
# spec/support/capybara.rb
require 'capybara/rails'
require 'capybara/rspec'
require 'capybara/poltergeist'
Capybara.javascript_driver = :poltergeist
# spec/support/factory_girl.rb
RSpec.configure do |config|
config.include FactoryGirl::Syntax::Methods
end
# spec/support/database_cleaner.rb
RSpec.configure do |config|
config.before(:suite) do
DatabaseCleaner.clean_with(:truncation)
end
config.before(:each) do
driver_shares_db_connection_with_specs = (Capybara.current_driver == :rack_test)
DatabaseCleaner.strategy = driver_shares_db_connection_with_specs ? :transaction : :truncation
DatabaseCleaner.start
end
config.append_after(:each) do
DatabaseCleaner.clean
end
end
Now we have a framework for testing which covers nearly every case.
Have a look at the rspec
subcommands under rails generate
for the types of tests that can be generated.
A testing framework primarily targeted at BDD with a nifty DSL that lets you write expressive tests.
More than a test runner, rspec
does all the heavy lifting to make writing and reading tests easy and fun.
An acceptance test framework for writing tests which simulate user behaviour. It uses a driver to run tests in a browser.
When combined with rspec, we can write a test like this:
RSpec.feature "Widget management", :type => :feature do
scenario "User creates a new widget" do
visit "/widgets/new"
fill_in "Name", :with => "My Widget"
click_button "Create Widget"
expect(page).to have_text("Widget was successfully created.")
end
end
Here, rspec provides the feature
, scenario
, and expect
methods, while capybara provides the visit
, fill_in
, click_button
and have_text
methods.
A library for generating fake data for use in your tests. This is better than hard-coding test data, as it reduces the possibility of accidentally hard-coding your application to make the test pass.
For example:
Forgery(:internet).email_address
#=> "krainboltgreene@crt.net"
See also faker.
A library for setting up test data objects.
Instead of manually creating objects in the database to use during a test run, factory_girl
can create them for you (and has various options for persisting them or not).
Note: this is not fast, and should probably be avoided in unit tests in favour of unpersisted ActiveRecord
objects, or using rspec mocks.
Sometimes persisting to the database during a test is essential (feature tests) or desirable (you want to test some complex relationship), so ensuring each test begins with a clean slate is vital.
database_cleaner does this using a number of strategies (which we have configured above).
Database seeds.
Rails does have this built in, but seedbank
gives us a little more structure, and some nice features like dependencies.
RSpec Rails Documentation
Canonical documentation on writing tests, the available syntax, test types and configuration.
Better Specs
A collection of best-practice recommendations for writing better rspec, complete with code samples.
Giant Robots Smashing Into Other Robots–the Thoughtbot blog; specifically: