Setting up RSpec, Cucumber and Factory Bot

(The Enova Way)

At Enova, we use both Test Driven Development and Behavior driven development to build our applications. However, if you’re new to programming and Ruby on Rails, the concept of Test Driven Development can seem daunting. It may seem longer to write the tests than it would to write the application. The aim of this tutorial is to help reduce the barrier to writing tests. We won’t go into too much detail about RSpec, Cucumber, or Factory Bot. This is purely a getting started guide.

First of all, we need the gems used to test. We’ll add rspec-rails, factory_bot_rails, and cucumber-rails to our Gemfile. It’s also highly recommended to use database_cleaner as well:

group :development, :test do
  gem 'rspec-rails', '~> 3.5'
  gem 'factory_bot_rails'
  gem 'cucumber-rails'
  gem 'database_cleaner'
end

Next we’ll run some commands to get everything setup:

$ bundle install
$ rails generate rspec:install

This bootstraps your Rails application with RSpec. It will generate a spec/ folder which will be where you put all your RSpec tests. You can remove the test/ folder if it exists. Now run:

$ rails generate cucumber:install

This will bootstrap your Rails application with Cucumber. It generates some cucumber scripts and also a features/ folder. Inside this folder you will see step_definitions/ and support/.

Next create the file spec/support/factory_bot.rb and paste in:

# spec/support/factory_bot.rb
RSpec.configure do |config|
  config.include FactoryBot::Syntax::Methods
end

This makes method calls less verbose. For example instead of FactoryBot.build you can now use build.

Next, uncomment the following line in spec/rails_helper.rb to autoload files in the support/ directory.

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

Everything is now setup. The next step is to generate a test and create a factory. Then we need to make sure everything passes.

Generating a test and running it

An RSpec test will be generated whenever you generate a model or controller. RSpec also offers generators to generate a test only. For example here’s how to generate a test for the model, Widget.

$ rails generate rspec:model widget

Check the RSpec documentation on generators to learn more.

Fun fact: with Factory Bot installed, a factory will also be generated when you generate a test.

Here are the files created when running the above RSpec generator. This should also generate a Factory Bot file spec/factories/widgets.rb.

# spec/models/widget_spec.rb
require 'rails_helper'
RSpec.describe Widget, type: :model do
  pending "add some examples to (or delete) #{__FILE__}"
end

# spec/factories/widgets.rb
FactoryGirl.define do
  factory :widget do
  end
end

To run the test:

$ bundle exec rspec spec

Running a Cucumber feature

Unlike RSpec tests, Cucumber features are not automatically generated. You will need to add a .feature file inside the features/ folder. That’s all it takes to add a feature. You will then need to add a step_definition inside the step_definitions/ folder. This will contain ruby code that will run each of your cucumber steps.

Let’s take the widget example from above. If we’re adding a feature for a widget then the structure could look something like this :

features/
├── some_widget_feature.feature
├── step_definitions/
│      ├── widget_steps.rb
├── support/
└── env.rb

Next, you’ll want to add this code to your env.rb file so it loads the Factory Bot factories and run database_cleaner:

require 'cucumber/rails'
require 'factory_girl'

def load_fixture(filename)
  path = Rails.root.join('features', 'support', 'fixtures', filename)
  File.open(path, 'r', &:read)
end

World(FactoryGirl::Syntax::Methods)
World(Rails.application.routes.url_helpers)

ActionController::Base.allow_rescue = false

begin
  require 'database_cleaner'
  require 'database_cleaner/cucumber'
  DatabaseCleaner.strategy = :transaction
rescue NameError
  raise 'You need to add database_cleaner to your Gemfile (in the :test group) if you wish to use it.'
end

Cucumber::Rails::Database.javascript_strategy = :truncation

Finally, to run your cucumber tests:

$ rake cucumber

or

$ bundle exec cucumber

✅ RSpec
✅ Cucumber
✅ Factory Girl

Happy testing!