Rspec, SimpleCov, Capybara & FactoryBot Setup (for Ruby Testing)

Setup Rspec & Capybara

Add these gems to your Gemfile in the development, test group. This group applies to both the development and test environments.

gem :development, :test do
  gem 'rspec-rails'  
  gem 'factory_bot_rails'  
  gem 'simplecov'
  gem 'simplecov-rcov'
  // other gems in the dev+test group
end

then run bundle install

(You’ll notice by default your Gemfile already has: gem 'capybara' which we will be using. The // comment lines above signify the other content inside of your :development, :test group already. Be sure to check the gems already in your these groups for duplicates. If you have gems with version numbers, you can safely remove the version numbers for the purpose of this demo.)

then run rails generate rspec:install

Notice that this has created:

a hidden file .rspec

a folder spec/

spec/spec_helper.rb

spec/rails_helper.rb

COMMIT YOUR CHANGES HERE BEFORE CONTINUING.

1/ Configure SimpleCov for Coverage Reports

Open spec/rails_helper.rb and add the code shown in orange below. (just below the line require 'rspec/rails'). Also, be sure to add the configuration for FactoryBot in the Rspec config (also shown in orange.) Note here I like to remove the default comments that come with the generated file (I personally find them distracting), and I have done so here.

require 'spec_helper'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../config/environment', __dir__)

abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'rspec/rails'

if( ENV['COVERAGE'] == 'on' )
  require 'simplecov'
  require 'simplecov-rcov'
  class SimpleCov::Formatter::MergedFormatter
    def format(result)
      SimpleCov::Formatter::HTMLFormatter.new.format(result)
      SimpleCov::Formatter::RcovFormatter.new.format(result)
    end
  end
  SimpleCov.formatter = SimpleCov::Formatter::MergedFormatter
  SimpleCov.start 'rails' do
    add_filter "/vendor/"
    add_filter "/test/"
  end
end


begin
  ActiveRecord::Migration.maintain_test_schema!
rescue ActiveRecord::PendingMigrationError => e
  puts e.to_s.strip
  exit 1
end

RSpec.configure do |config|
  config.fixture_path = "#{::Rails.root}/spec/fixtures"
  config.use_transactional_fixtures = true
  config.infer_spec_type_from_file_location!

  config.filter_rails_from_backtrace!
end
Capybara.default_driver = :rack_test

Now create a spec/features/ using

mkdir spec/features

Finally, I recommend you add the coverage/ folder — which is where you code coverage reports will be automatically output to — into your .gitignore file. Just open .gitignore and add a line that reads:

coverage/

Alternatively, you can decide to check-in your coverage reports with each commit.

What this code above will do is it will generate coverage reports whenever you run RSpec using COVERAGE=on, like so:

COVERAGE=on ./bin/rake rspec

You simply prepend (put before) the text COVERAGE=on to the rspec command as you run it.

Alternatively, modify the Ruby code above to remove the line if( ENV['COVERAGE'] == 'on' ) (and its end statement) and your coverage reports will run every time you run rspec.

COMMIT YOUR CHANGES HERE BEFORE CONTINUING.

2/ Set up a Route and A Blank Welcome Page

Now let’s take a quick detour and set up a basic Rails route and view. Go to config/routes.rb and add

Rails.application.routes.draw do
  root to: "welcome#index"
end

Create an empty controller welcome_controller.rb:

rails generate controller Welcome

Create a folder views/welcome/index.erb

In this file put

Hello World

COMMIT YOUR CHANGES HERE BEFORE CONTINUING.

3/ Setup Capybara

To turn Capybara on, go to rails_helper.rb, again and again, and modify the RSpec.configure block. Add the config.include Capybara::DSL to the RSpec.configure block.

RSpec.configure do |config|
  config.fixture_path = "#{::Rails.root}/spec/fixtures"
  config.use_transactional_fixtures = true
  config.infer_spec_type_from_file_location!

  config.filter_rails_from_backtrace!
  config.include FactoryBot::Syntax::Methods
  config.include Capybara::DSL
end

Notice that there is an important setting here that is already enabled by default: config.infer_spec_type_from_file_location!

This tells Rspec that the specs in the system/ folder automatically feature specs, the specs in the requests/ folder are automatically request specs, etc.

Now go back to spec/features/

In this folder, create a file called math_spec.rb. When you make a feature spec, you must ‘tell’ Rspec it is a feature spec in one of two ways:

1) If the setting config.infer_spec_type_from_file_location! is on (as seen above), a spec in the features folder will automatically be considered a feature spec, or

2) you specify it is a feature spec using type: :feature (as shown below).

require 'rails_helper'

describe "take a quiz", type: :feature do
  it "asks me to add to two numbers" do
    visit '/'
    expect(page).to have_content 'What is 5+2'
  end
end

If we run rspec or ./bin/rake spec , we see that we can’t find the text ‘What is 5+2’ inside of ‘Hello world’

Excellent! A failing spec. Just for shoots & gurgles, let’s change the spec like so:

Add the line shown in orange and remove the line with the strikethrough text.

require 'rails_helper'

describe "take a quiz", type: :feature do
  it "asks me to add to two numbers" do
    visit '/'
    expect(page).to have_content 'What is 5+2'
    expect(page).to have_content 'Hello World'
  end
end

Run bin/rake spec again and we get a passing spec as expected.

COMMIT YOUR CHANGES HERE BEFORE CONTINUING.

4/ Switch from Rack-Test To a Javascript Driver

TODO: (write something here)

5/ Understanding Transactional Fixtures

TODO: (write something here)

6/ Setting Up FactoryBot

Go back to rails_helper.rb and add this:

RSpec.configure do |config|
  config.fixture_path = "#{::Rails.root}/spec/fixtures"
  config.use_transactional_fixtures = true
  config.infer_spec_type_from_file_location!

  config.filter_rails_from_backtrace!
  config.include FactoryBot::Syntax::Methods
end

TODO: (write something here)

7/ FactoryBot Basics