Setup Rails testing stack with RSpec, Database Cleaner, FactoryBot, Shoulda Matchers and VCR

Setup Rails testing stack with RSpec, Database Cleaner, FactoryBot, Shoulda Matchers and VCR

Hello there, in this post, i'm going to setup RSpec and other tools inside a Ruby on Rails application and create a super consistent stack of tests.

Content of this post

I'm going to use the --api mode to generate a new Rails app since i don't want to create tests with Capybara or Cucumber in this case. I'm using Ruby 3.0.0 and Rails 6.1.4.1.

Creating a new project

rails new myapp -T --api

Adding new dependencies

Add these gems to their specific group:

# Gemfile

group :development, :test do
  gem 'rspec-rails', '~> 5.0.0'
end

group :test do
  gem 'database_cleaner-active_record', '~> 2.0.1'
  gem 'factory_bot', '~> 6.2.0'
  gem 'shoulda-matchers', '~> 5.0'
  gem 'faker', '~> 2.19.0'
  gem 'vcr', '~> 6.0.0'
end

Install everything using bundler:

bundle install

Setup RSpec

rails generate rspec:install

This command generates a new folder called spec* and new files with default RSpec configuration to the project, if everything was executed correctly we can run:

bundle exec rspec

In the recent created file rails_helper.rb uncomment this line to import support files we will create:

Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }

Screen Shot 2021-08-23 at 18.38.20.png

Setup DatabaseCleaner

DatabaseCleaner is a tool that helps us keep our test database clean. In this case we are using only DatabaseCleaner for ActiveRecord, however there are a lot of other options like Redis.

Create a new spec/support/database_cleaner.rb file:

RSpec.configure do |config|
  config.before(:suite) do
    DatabaseCleaner.strategy = :transaction
    DatabaseCleaner.clean_with(:truncation)
  end

  config.around(:each) do |example|
    DatabaseCleaner.cleaning do
      example.run
    end
  end
end

Setup FactoryBot

To setup FactoryBot, just require it in the rails_helper.rb file after require 'rspec/rails':

require 'rspec/rails'
require 'support/factory_bot'

Setup transactional_fixtures to false:

RSpec.configure do |config|
# ...
config.use_transactional_fixtures = false
# ...
end

Create a new support/factory_bot.rb file:

RSpec.configure do |config|
  config.include FactoryBot::Syntax::Methods
end

Setup Shoulda Matchers

Shoulda Matchers provides RSpec- and Minitest-compatible one-liners to test common Rails functionality that, if written by hand, would be much longer, more complex, and error-prone.

Create a new spec/support/shoulda_matchers.rb file:

Shoulda::Matchers.configure do |config|
  config.integrate do |with|
    with.test_framework :rspec
    with.library :rails
  end
end

Setup VCR

Record your test suite's HTTP interactions and replay them during future test runs for fast, deterministic, accurate tests.

You can update your spec_helper.rb like this:

require 'vcr'

VCR.configure do |c|
  c.ignore_localhost = true
  c.ignore_hosts 'api.segment.io'
  c.cassette_library_dir = 'spec/cassettes'
  c.hook_into :webmock
  c.configure_rspec_metadata!
end

Conclusion

Now we can create our specs, including specs that depend on third api calls, VCR will take care about it creating cassetes to record requests.