Setting Up Cucumber for your Rails Projects
This is the 15th Testing Tuesday episode. Every week we will share our insights and opinions on the software testing space. Drop by every Tuesday to learn more! Last week we showed you how to set up RSpec with standalone Ruby applications and Rails web applications.
Set up Cucumber for Ruby applications
For all Ruby applications you can use the cucumber gem. In the screencast we walk you through creating a basic Ruby project and installing cucumber using bundler. We implement one passing scenario and make Cucumber use RSpec expectations instead of Minitest that ships with Ruby.
Set up Cucumber for Rails web applications
There is a special cucumber-rails gem that makes setting up Cucumber with Ruby on Rails web applications even easier. It contains a generator that prepares your app by adding preconfigured cucumber profiles, rake tasks and a Cucumber script. We'll look into the advantages in more detail in the screencast.
Testing Tuesday #8: Behavior-Driven Integration and Unit Testing
Testing Tuesday #4: Continuous Integration and Deployment with Cucumber
Testing Tuesday #3: Behavior-Driven Development with Cucumber
Setting up Cucumber
Ahoy and welcome! My name is Clemens Helm and this is Codeship Testing Tuesday #15. Last week I showed you how to set up RSpec for Ruby and Rails projects. This week we're gonna do the same thing for Cucumber. Thanks to Rafael who left me a comment and showed me an even faster way of setting up RSpec for a new project. I'll use your technique in this episode.
We're gonna set up one standalone Ruby application and one Rails application, because there are a few differences in the setup. Let's get started with the standalone application first:
Let's create an empty directory
cucumber-app for our application.
cd cucumber-app In the directory we initiate bundler by calling
bundle init. This will create a Gemfile for us. Let's add the Cucumber gem
gem "cucumber" and install it by running
When we run
cucumber now, it tells us "No such file or directory - features". Cucumber will look for our features in the "features" directory, so let's create it
mkdir features and run
cucumber again. It ran successfully without executing any features. Let's add a simple feature:
mate ., create
Feature: Warm welcome In order to make my users feel comfortable on my website As the website owner I want to greet them appropriately Scenario: Greeting a sailor Given I am a sailor Then I want to be greeted "Ahoy and welcome!"
Running cucumber lists the missing step definitions. Let's copy these snippets into a file "sailor_steps.rb"
Given(/^I am a sailor$/) do @user = User.new type: :sailor end Then(/^I want to be greeted "(.*?)"$/) do |greeting| @user.greeting.should == greeting end
Now cucumber tells us that it doesn't know the constant User. Let's add a user class in
lib/user.rb. Cucumber still complains, because we need to require
user.rb somewhere. Let's do that in the "sailor_steps.rb" file
We get a different error message now, because the user's constructor doesn't accept any arguments yet. But how did Cucumber know where to look for the
User class? We didn't eplicitly tell it to look in the
lib directory. Like I already showed you in last week's episode, there's a global variable that contains the load paths of source files. When we print this variable in our Cucumber steps
puts $: it will list our "lib" directory as first entry of the load paths. Cucumber added this directory, because there's a convention to put your Ruby classes there.
Ok, let's remove the puts statement again. Cucumber complained about our constructor, so let's make it accept a "type" argument:
def initialize type: type end
Now Cucumber still misses the "greeting" method.
def greeting end
And now Cucumber complains that it doesn't know the method "should". The reason is that Cucumber doesn't contain the RSpec matchers. By default, you can use "Minitest" which is included in the Ruby standard library. We could rewrite our step definition as:
Then(/^I want to be greeted "(.*?)"$/) do |greeting| assert_equal @user.greeting, greeting end
This will give us the expected result. But how can we stick with our RSpec syntax? (undo change)
We have to install "rspec-expectations". Let's add them to our Gemfile.
cucumber And now our feature runs on RSpec. Great! Let's fix the error by greeting our sailor correctly:
def greeting "Ahoy and welcome!" end
Now our feature works!
But what if we want to greet sailors on our Rails web application as well? Let's create a new Rails application for this.
rails new rails-greeter We could use the
cucumber gem here as well, but there is a special
cucumber-rails gem that comes with additional goodies for Rails. Let's add it to the test-environment in our Gemfile:
group :test do gem 'cucumber-rails', require: false end
require: false so Cucumber isn't loaded when we run other testing tools like RSpec. The cucumber command will require the cucumber gem anyway. It's also recommended to add the "database_cleaner" gem to your Gemfile. Database cleaner makes sure that your database is cleaned after every scenario.
group :test do gem 'cucumber-rails', require: false gem 'database_cleaner' end
Let's install these gems with Bundler.
Cucumber-Rails provides us with a generator script to set up cucumber. We only need to run
rails generate cucumber:install.
This will do a few things:
It creates a cucumber.yml file. This defines 3 cucumber profiles: default, work in progress and rerun. You can run cucumber with each of these profiles by passing the
--profileoption. For example, if we run the "wip" profile, it will run scenarios tagged with "@wip" and complain, if there are more than 3 of them. You can customize the options for these profiles or add your own profiles in this file.
It also creates a cucumber script. In Rails 4 this actually belongs in the "bin" directory, so let's move the file and delete the "script" directory. This script makes sure that the right cucumber distribution is required.
The install script also adds directories for features, step definitions and support files and already creates the first support file "env.rb" which contains the Cucumber configuration.
And it creates a rake file to run cucumber as a rake task.
rake -T | grep cucumberThere are several tasks to run only subsets of your features. In general I recommend against using them though, because rake increases the load time for cucumber.
It modifies the database.yml and creates an own cucumber enviroment which inherits from the test environment by default.
I won't go into detail about how to write your features again, because it works the same way as for other Ruby applications. So the main advantage of the
cucumber-rails gem is that it hooks directly into our rails application by creating everything that's necessary with the installation script.
Stay up to date
We'll never share your email address and you can opt out at any time, we promise.