Configure RSpec and Capybara with Ruby on Rails
In this tutorial I’m going to show you how to configure your Rails app to use RSpec and Capaybara. In addition, we will also install and configure Factory Bot Rails and Database Cleaner, since these Gems help with a better testing experience.
1. Create a New App and Skip Tests
Since we’ll be using rspec-rails as the test framework, we need to skip the default Rails test suite.
-
Open up a new terminal and create a new Rails app. Be sure to pass the
-T
flag. This will skip the default test suiterails new rspec-demo -d=postgresql -T cd rspec-demo/
2. Install and Configure RSpec Rails
rspec-rails is a testing framework for Rails 3.x, 4.x and 5.x. rspec-rails extends Rails’ built-in testing framework to support rspec examples for requests, controllers, models, views, helpers, mailers and routing.
TLDR: rspec-rails is a popular alternative to the default Rails test suite.
-
Add
gem 'rspec-rails'
to yourGemfile
in the:development, :test
group
.group :development, :test do gem "rspec-rails", "~> 3.8", ">= 3.8.2" end
- In the terminal window, run
bundle install
- In the terminal window, run
rails generate rspec:install
per rspec-rails instructions
3. Install and Configure Factory Bot Rails
factory_bot is a fixtures replacement with a straightforward definition syntax, support for multiple build strategies (saved instances, unsaved instances, attribute hashes, and stubbed objects), and support for multiple factories for the same class (user, admin_user, and so on), including factory inheritance.
TLDR: factory_bot makes it easy to create sample data to test against
-
Add
gem 'factory_bot_rails'
to yourGemfile
in the:development, :test
group
.group :development, :test do gem "rspec-rails", "~> 3.8", ">= 3.8.2" gem "factory_bot_rails", "~> 5.1" end
- In the terminal window, run
bundle install
- Create a new directory at
mkdir spec/factories/
by runningmkdir spec/factories
in the terminal window. This is required by factory_bot_rails - Create a new directory at
spec/support/
by runningmkdir spec/support
in the terminal window - Create
factory_bot.rb
inspec/support
by runningtouch spec/support/factory_bot.rb
in the terminal window -
Open
spec/support/factory_bot.rb
and add the following:RSpec.configure { |config| config.include FactoryBot::Syntax::Methods }
- Open
spec/rails_helper.rb
and uncommentDir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }
.
4. Install and Configure Capybara
Capybara is a library written in the Ruby programming language which makes it easy to simulate how a user interacts with your application.
-
Add
gem 'capybara'
to yourGemfile
in the:development, :test
group
.group :development, :test do gem "rspec-rails", "~> 3.8", ">= 3.8.2" gem "factory_bot_rails", "~> 5.1" gem "capybara", "~> 3.29" end
- In the terminal window, run
bundle install
- Create
capybara.rb
inspec/support
by runningtouch spec/support/capybara.rb
in the terminal window -
Open
spec/support/capybara.rb
and add the following:require "capybara/rspec"
5. Install and Configure Database Cleaner
Database Cleaner is used to ensure a clean state for testing.
-
Add
gem 'database_cleaner'
to yourGemfile
in the:test
group
.group :test do gem "database_cleaner", "~> 1.7" end
- In the terminal window, run
bundle install
-
Open
spec/support/capybara.rb
and add the following:require "capybara/rspec" RSpec.configure do |config| config.use_transactional_fixtures = false config.before(:suite) do raise(<<-MSG) if config.use_transactional_fixtures? Delete line `config.use_transactional_fixtures = true` from rails_helper.rb (or set it to false) to prevent uncommitted transactions being used in JavaScript-dependent specs. During testing, the app-under-test that the browser driver connects to uses a different database connection to the database connection used by the spec. The app's database connection would not be able to access uncommitted transaction data setup over the spec's database connection. MSG DatabaseCleaner.clean_with(:truncation) end config.before(:each) { DatabaseCleaner.strategy = :transaction } config.before(:each, type: :feature) do # :rack_test driver's Rack app under test shares database connection # with the specs, so continue to use transaction strategy for speed. driver_shares_db_connection_with_specs = Capybara.current_driver == :rack_test unless driver_shares_db_connection_with_specs # Driver is probably for an external browser with an app # under test that does *not* share a database connection with the # specs, so use truncation strategy. DatabaseCleaner.strategy = :truncation end end config.before(:each) { DatabaseCleaner.start } config.append_after(:each) { DatabaseCleaner.clean } end
- Comment out
config.use_transactional_fixtures = true
fromspec/rails_helper.rb
6. Create Our First Test (Optional)
Now that our app’s test suite is configured with RSpec, Capybara, Factory Bot Rails and Database Cleaner, let’s write some tests to ensure everything is working.
- In the terminal window, run
rails g model post title body:text
to generate a newmodel
. - In the terminal window, run
rails db:migrate
to migrate the database. This should have generatedspec/models/post_spec.rb
andspec/models/post_spec.rb
. -
Update
spec/models/post_spec.rb
with the following code:RSpec.describe Post, type: :model do describe "validations" do let(:post) { FactoryBot.build(:post) } it "should have a title" do post.title = nil expect(post).to_not be_valid end end end
-
Run
rspec
. The test should fail.F Failures: 1. Post validations should have a title Failure/Error: expect(post).to_not be_valid expected #<Post id: nil, title: nil, body: "MyText", created_at: nil, updated_at: nil> not to be valid # ./spec/models/post_spec.rb:8:in `block (3 levels) in <top (required)>' Finished in 0.16554 seconds (files took 4.71 seconds to load) 1 example, 1 failure Failed examples: rspec ./spec/models/post_spec.rb:6 # Post validations should have a title
-
Open
app/models/post.rb
and add the following validation:class Post < ApplicationRecord validates :title, presence: true end
-
Run
rspec
. The test should pass.. Finished in 0.10767 seconds (files took 1.03 seconds to load) 1 example, 0 failures
- This was just an exercise to ensure the test suite is running correctly. For more examples on how to configure your tests, I recommend looking at RSpec Rails Examples and Better Specs