How To Configure Rails Tests with RSpec, FactoryBot and Capybara

Written by felipe-augusto-rosa | Published 2020/09/09
Tech Story Tags: rails | rspec | factory-bot | capybara | testing | ruby-on-rails | environment-setup | coding

TLDR How To Configure Rails Tests with RSpec, FactoryBot and Capybara is a guide on how to set up your environment for using these technologies. RSpec is a Ruby written language for testing Ruby code. FactoryBot allows us to create an object or a collection of objects with predefined sets of values for our tests. Database Cleaner is a tool used to clean the database after tests. It is used to simulate how a user interacts with your web application using Ruby. Database cleaner is useful for situations where tests create a new object in the database that could interfere with other tests.via the TL;DR App

So, you're asked to test your application but have no idea how to begin. Or you read about TDD, RSpec, FactoryBot, Capybara, and maybe you didn't understand what they were meant for, or maybe when you tried to run them into your project nothing worked.
This is a beginner guide on how to set up your environment for using these technologies. If you are not familiar with these terms, here is a brief explanation about them:
  • TDD (Test Driven Development): It is a development technique where the tests are built before starting the real code. In this process, the tests are created based on the requirements, and the code is implemented to pass the tests.
  • RSpec: It's a Ruby written language for testing Ruby code. Yeah! This is your testing tool. A language created with Ruby in order to offer an interface to write readable tests for your project. It is an alternative for Minitest, the default Rails testing framework. This is a test example for a User model with RSpec.
RSpec.describe User, type: :model do
  it 'name should not have less than 3 characters' do
    user = User.new
    user.name = 'ab'
    user.valid?
    expect(user.errors[:name]).to include('is too short (minimum is 3 characters)')
  end
end
  • Capybara: Another testing tool - a library that enables browser interaction using Ruby. In other words, this one is used to simulate how a user interacts with your web application. It is combined with RSpec to create the 'feature testing' environment. Here is an example of testing with RSpec and Capybara for a 'login' page:
RSpec.feature 'Users', type: :feature do
    it 'are redirected to root page when login is sucessfull' do
        fill_in 'session_username', with: 'myusername'
        fill_in 'session_password', with: 'mypassword'
        find("input[type='submit']").click
        expect(page).to have_current_path(root_path)
    end
end
  • DatabaseCleaner: As the name says, it is a tool used to clean the database after tests. It is useful for situations where running a test creates a new object in the database that could interfere with other tests.
  • FactoryBot: It allows us to create an object or a collection of objects with predefined sets of values for our tests. What does it mean? If we have a 'User' model, we can create predefined values for different kinds of users. That means it is possible to define a 'random user' and a 'regular user' factory and use them inside your tests, without the need to declare every time. This is a really simple example of how it can be declared used inside our tests:
FactoryBot.define do
  factory :user do
    name { 'Simple User' }

    factory :user_random do
      sequence(:name) { |n| "User #{n}" }
    end
  end
end
RSpec.describe User, type: :model do
    it '...' do
        user = create(:user) # user.name: 'Simple User'
        random_user = create(:user_random) # random_user.name: 'User 1'
        random_user = create(:user_random) # random_user.name: 'User 2'
    end
end
Ok, now that you are already familiar with these terms we can move on and configure your project to use these technologies.

Setting up the environment

Although it seems simple, it can take some time to set up this testing environment for the first time as a beginner.
Note: I'm using Rails 5.
At first, let's get these babies inside our project. Open the Gemfile and make sure it has the following gems, then run 'bundle install'.
group :test do
  # ...
  gem 'rspec-rails'
  gem 'factory_bot_rails'
  gem 'capybara'
  gem 'database_cleaner'
end
Now we have to generate the 'spec' folder containing the helpers for RSpec:
rails generate rspec:install
This command creates a file called 'rails_helper.rb' inside the spec folder. We must change this file in order to set up the RSpec environment along with FactoryBot, Capybara, and DatabaseCleaner, so the next steps are all inside the 'spec/rails_helper.rb' file.
For FactoryBot, let's add this line inside the RSpec.configure block. It includes factory bot inside our tests.
RSpec.configure do |config|
  # ...
  config.include FactoryBot::Syntax::Methods
end
To include Capybara, we need to require the gem inside our helper. So let's add this line at the beginning of the file:
require 'capybara/rails'
And to complete, the DatabaseCleaner. This one has some additional configs, so it has some more lines of set up.
First, let's change the config 'config.use_transactional_fixtures = true' to 'false'. It will disable the native rails cleaner.
RSpec.configure do |config|
  # ...
  config.use_transactional_fixtures = false	# CHANGE THIS LINE TO FALSE
  # ...
end
Then, we can add the DatabaseCleaner configurations:
RSpec.configure do |config|
  # ...
  config.before(:suite) { DatabaseCleaner.clean_with(:truncation) }	
  config.before(:each) { DatabaseCleaner.strategy = :transaction }	
  config.before(:each, js: true) { DatabaseCleaner.strategy = :truncation }	
  config.before(:each) { DatabaseCleaner.start }
  config.after(:each) { DatabaseCleaner.clean }
end
And that's it! Now we are good to go with our testing. Simple right?
In short, the steps are:
  • Add the gems to Gemfile and 'bundle install';
  • Generate RSpec configs: 'rails generate rspec:install';
  • Modify 'specs/rails_helper.rb' file to include all gems in RSpec.
The final 'specs/rails_helper.rb' (without the commented stuff) should be something like this:
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'
require 'capybara/rails'

begin
  ActiveRecord::Migration.maintain_test_schema!
rescue ActiveRecord::PendingMigrationError => e
  puts e.to_s.strip
  exit 1
end
RSpec.configure do |config|
  config.before(:suite) { DatabaseCleaner.clean_with(:truncation) }
  config.before(:each) { DatabaseCleaner.strategy = :transaction }
  config.before(:each, js: true) { DatabaseCleaner.strategy = :truncation }
  config.before(:each) { DatabaseCleaner.start }
  config.after(:each) { DatabaseCleaner.clean }
  config.fixture_path = "#{::Rails.root}/spec/fixtures"
  config.use_transactional_fixtures = false
  config.infer_spec_type_from_file_location!
  config.filter_rails_from_backtrace!
  config.include FactoryBot::Syntax::Methods
end
And that's it, folks! I hope I could help you start testing your projects and gave you an idea about the uses of each tool. Good luck on your testing journey and happy coding!

Written by felipe-augusto-rosa | Just kind of a full stack developer trying to be a real full stack developer.
Published by HackerNoon on 2020/09/09