Services Spotlight:

How to Setup Cucumber in a Rails Engine

Written By Corlew Solutions
Updated August 26, 2019
Published June 20, 2016
Why Corlew Solutions?

We write great software and provide amazing technical support. Contact us today if you need help with a software project:

  • Website: Send an inquiry
  • Email:

Article Technology Info

This article discusses the following technologies:

  • Cucumber - A testing framework for Behavior Driven Development
    (website | docs)
  • Rails Engines - Small applications that provide functionality to larger Rails applications.
  • Ruby on Rails - An open source web application framework written in Ruby.
    (website | docs)

In this article, we will learn how to setup Cucumber in a brand new engine that was generated using the rails plugin new command. If your engine is already created, you will be able to follow along and create/edit the necessary files in your current project.

Testing an engine using Cucumber is very similar to testing a full blown Rails application. There are some differences in the setup, but for the most part, the process is similar. This isn’t surprising since a Rails app is just a “supercharged engine” according to the Getting Started with Engines guide. One thing to understand right off-the-bat is engine’s are tested through a host Rails application (called “the dummy application” in the Rails documentation) which resides in the engine’s spec/dummy folder. With a non-engine gem, you would typically use Cucumber to test the gem modules directly; in an engine, you can still do that if needed, but you also have the extra ability to use the dummy Rails application for more advanced testing with tools like Capybara. This gives you a great opportunity to test your engine in a way that it will actually be used - inside a real Rails app.

Adding Cucumber to Existing Engines

In order to keep the article short and focused, we’re going to proceed by creating and modifying a brand new engine. However, the steps for adding Cucumber to an existing engine are almost identical so you will be able to follow along and make related changes to your existing engine. We’re going to review all the important files so you won’t miss anything if your engine was built using a different process from the one below.

Example Engine

A bare bones sample engine has been created on GitHub at you want to take a look at working code.

RSpec, Test Unit, minitest Oh My…

Most people tend to use Cucumber with another testing framework like RSpec. Unless it’s told otherwise, Rails will attempt to use minitest as the default testing framework. In this article, we will assume RSpec is used, but it’s straight forward to use one of the other testing framework. We have a companion article named How To Setup RSpec in a Rails Engine and it would be best to work through that article first if you plan on using RSpec and Cucumber together.

The process for testing engines involves creating a Rails application called the “dummy application” and this dummy application typically lives at spec/dummy for RSpec or test/dummy for Test Unit. We will keep that pattern for this article and assume the dummy application lives in spec/dummy.

Create The Engine

First things first, let’s create the sample engine. We’re going to call our engine blorgh which is the name used in the Getting Started with Engines guide. Also, for this sample engine, we don’t particularly care if it’s a full or mountable engine. If you’re building a new engine and aren’t sure which way to go, Stackoverflow has a good thread on full vs mountable engines. You can always change your engine around later if you’re unsure. For now, we’ll create a full engine by executing:

rails plugin new blorgh --dummy-path=spec/dummy --skip-test --full

This will create an engine with a dummy rails application inside the spec/dummy folder. It will also tell the generator not to create a test folder for Test Unit tests.

The above command will use the latest version of Rails installed on the machine. If you want to use a specific version of rails, you can target a version by putting the version between two underscores:

rails _5.2.3_ plugin new blorgh --dummy-path=spec/dummy --skip-test --full

Setup Cucumber in the Rails Engine

Setup the dummy Application

Our sample engine defines a dummy app at spec/dummy. If your engine doesn’t have a spec/dummy app, copy the one from the sample engine into your engine.

Open the spec/dummy/config/application.rb file and somewhere near the top, you’ll see a line where your engine is required. If you’re looking at the sample app, it will say require “blorgh”. Make sure your engine has a similar line that loads your engine. What you’re actually doing here is requiring the main gem file inside your engine’s lib folder. So, if your engine is named my_engine, then you probably have a lib/my_engine.rb file and you would need require “my_engine” inside your application.rb.

While still inside the application.rb file, take a look at how rails is required. Engine’s that use Test Unit as the testing framework have a require “rails/all” line near the top. Engine’s that are created with –skip-test don’t require all of rails because that would load the minitest library. Take a look at the sample engine and make sure your engine requires the same components. For Rails 5.2.3 this looks like:

require "rails"
# Pick the frameworks you want:
require "active_model/railtie"
require "active_job/railtie"
require "active_record/railtie"
require "active_storage/engine"
require "action_controller/railtie"
require "action_mailer/railtie"
require "action_view/railtie"
require "action_cable/engine"
require "sprockets/railtie"
# require "rails/test_unit/railtie"

Your dummy rails application is completely setup at this point!

Setup .gitignore

We don’t want Git including the temporary files in the dummy app when we commit our changes so make sure .gitignore includes the following


Setup .gemspec

The rails plugin new command generates a starting .gemspec for your project. It’s a little too bare bones for our tastes and we actually prefer the one generated by the bundle gem which is an alternative gem generator. Inside the .gemspec file, find the following line:

s.files = Dir["{app.config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.rdoc"]

Replace it with the following which is generated by the bundle gem command:

s.files         = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
s.bindir        = "exe"
s.executables   = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
s.require_paths = ["lib"]

Setup bin/rails

The rails engine generator also created a bin/rails file for us. This file is important because Cucumber has an installer that we will execute and that installer won’t run unless this file exists. Here are some things you should do with this file:

  1. If your engine is missing this file, copy the one in the sample app to your engine.
  2. Make sure this file is executable on your file system. If it isn’t, chmod +x bin/rails
  3. Open the file and find the line that sets the ENGINE_PATH constant. Make sure that line references your engine’s name and not the name of the sample app.

If you take a quick look at this file, you may notice that it looks a little different then the bin/rails file you would find in a full Rails application. This version of bin/rails has been configured to work with engines. If you try to execute a command like rails new from inside the engine’s root folder, you’ll get an error message like the following:

Error: Command not recognized
Usage: rails COMMAND [ARGS]

The common Rails commands available for engines are:
 generate    Generate new code (short-cut alias: "g")
 destroy       Undo code generated with "generate" (short-cut alias: "d")

All commands can be run with -h for more information.

If you want to run any commands that need to be run in context
of the application, like `rails server` or `rails console`,
you should do it from application's directory (typically test/dummy).

When you execute rails in the shell, it’s smart enough to know to execute the bin/rails version inside your engine instead of the more general version.

Setup Rakefile

Rakefile is another file where we need to do some work. Merge the contents of Rakefile from the sample app into your engine’s Rakefile if there are differences. The most important lines that may be missing from your Rakefile are:

APP_RAKEFILE = File.expand_path("spec/dummy/Rakefile", __dir__)
load 'rails/tasks/engine.rake'
load 'rails/tasks/statistics.rake'

Make sure the path that sets APP_RAKEFILE says ../spec/dummy/Rakefile instead of ../test/dummy/Rakefile.

Also, depending on how you created your engine, your engine may simply have require “bundler/gem_tasks” . The sample engine probably has:

  require 'bundler/setup'
rescue LoadError
  puts 'You must `gem install bundler` and `bundle install` to run rake tasks`

Use the version from the sample engine.

Once you’ve made these lines you’ll be able to execute rake commands like rake db:drop from your engine’s root folder and the command will act on your dummy application.

Add database_cleaner

Cucumber’s default setup assumes you will be using the database_cleaner gem. Let’s add that to our engine so it will be available later. Open the .gemspec" file and add:

s.add_development_dependency "database_cleaner"

Install Cucumber

With the preliminary stuff out the way, let’s finally install Cucumber. Open your engine’s Gemfile file and add:

gem "cucumber-rails", "~> 1.8.0", require: false, group: :test

We have to put this in the Gemfile because we need to use the require: false option which isn’t supported in the .gemspec file.

Next, bundle the dependencies to make sure cucumber gets installed:

rm Gemfile.lock

Now, invoke the cucumber generator

rails g cucumber:install

Open the newly created features/support/env.rb file and add the following before the require ‘cucumber/rails’ line:

ENV["RAILS_ENV"] ||= "test"
require File.expand_path("../../spec/dummy/config/environment.rb", __dir__)
ENV["RAILS_ROOT"] ||= File.dirname(__FILE__) + "../../../spec/dummy"

Add Other Gem Dependencies

You may have noticed that your dummy application doesn’t have its own Gemfile. If you take a look at spec/dummy/config/boot.rb you’ll see that it tells bundler to use the Gemfile from your engine instead. If your dummy app needs other gems installed, you can add them as development dependencies in the engine’s .gemspec file or the engine’s Gemfile.

At this point, you probably have a dependency on sqlite3 because your dummy app is using it for the database. There’s nothing stopping you from using Postgres or MySQL, but sqlite3 is probably a good place to start. Make sure the following is in your engine’s .gemspec file:

s.add_development_dependency "sqlite3"

Testing It All Out

We can now do a couple things to verify everything is working properly. First, rebuild the test database to make sure the rake commands are working properly.

rake db:drop db:create db:migrate db:seed

If everything works, we should have test.sqlite3 and development.sqlite3 files in the spec/dummy/db folder. Depending on your version of Rails, you may need to specify RAILS_ENV=test when running the above rake commands.

Next, kickoff Cucumber by executing

cucumber # or cucumber features

If it’s working, it will report that zero scenarios were executed. Finally, try and run the dummy app and open it in the browser.

cd spec/dummy
rails s -b

Hopefully, you can fire up your browser and view the working dummy application.

Tips and Going Further

And just like that, we’re done! If you plan on using gems like capybara or factory_girl you simply need to add the gems as a development dependency in the engine’s .gemspec or Gemfile, then configure them as you normally would.

A Helpful Hint About Gem Dependencies

I recently wrote a gem that had a dependency on the font-awesome-rails gem. It loaded font-awesome and provided some extra helpers to the host application that used the engine. Everything worked great in a full Rails app, but when I tried to get my engine working with the dummy application I kept getting font-awesome import errors. The issue turned out to be the sass-rails gem. This gem is added by default to most Gemfile’s in a Rails app. However, nothing was telling my dummy app to load this gem.

The solution was to simply add sass-rails as a development dependency inside the engine. The lesson learned here is you have to be mindful about requiring everything your dummy app needs to run. A full Rails app will load some extra gems that aren’t present by default for dummy apps in an engine.

Renaming the Dummy App

If you’re not a fan of naming the dummy app “Dummy”, you’re not alone. Many people think the term “dummy” doesn’t accurately reflect the purpose of the application. If you peek into a couple engines on GitHub you’ll run across some alternative names like: sample_app, sample, test_app, and rails_app.

Changing the name of the application is easy. This is how you would rename it to “Rails App”:

  1. Rename your spec/dummy folder to spec/rails_app.
  2. Open the spec/rails_app/config/application.rb file and change module Dummy to module RailsApp.
  3. Search all the files in your engine for spec/dummy. Change the results to spec/rails_app.
  4. Change spec/dummy/config/initializers/session_store.rb to use _rails_app_session as the key.

On the other hand, the term “dummy” application is built into Rails and it was the good enough to become the default. Maybe it’s best to stick with dummy since it’s common and people will understand what it means, even if it’s not perfect. The choice is yours.

We hope you found this article useful. If you see any mistakes, missing features or ways to improve it, please let us know in the comments below so we can update its contents. If you're willing to link to us, we would sincerely appreciate it!

Corlew Solutions is a Web Design and Web Application Development company based in Fairfax Virginia, minutes away Washington D.C. If you're looking for great web design from the Northern Virginia area or web design from the Washington D.C. area we can help. Contact Us today!

comments powered by Disqus