Cucumber is a good Behavior Driven Development tool used for testing your application. I think it's the only framework that will enable both developers and non-technical people to write test cases. Isn't this pretty neat? In order to work with cucumber, the basic thing you need to have is good English. That's all.
It's very easy to setup Cucumber. First create your rails application (we are using Rails 3.0.3), here we need to skip over creating the test directory by giving the following command:
$ rails new projectname -T
-T option will skip the Test::Unit framework as we plan to use RSpec.
Next add this to your Gemfile:
group :test do gem 'rspec-rails' gem 'cucumber-rails' gem 'capybara' gem 'database_cleaner' end
For a Sinatra Application, you need to install the following gem:
Then install everything using bundler.
$ bundle install
The above installation will provide two generators. To setup cucumber in your Rails application, use the following commands:
For testing a rails application, we would need capybara and cucumber-rails for testing our rails application.
The below command will generate the necessary code to use capybara and rspec with cucumber for your rails project.
$ rails g cucumber:install --capybara --rspec
For testing a Sinatra Application, we need to give the following command to set the cucumber environment:
$ cucumber-sinatra init Myapp lib/my_app.rb
It will set the environment for cucumber. This command will generate the step definition and support folders. In the step definition folder, we have a file named web_steps.rb, which provides a broad set of steps that can be used in our specific steps file. In the support folder we have two files env.rb and paths.rb. This env.rb is a configuration file and paths.rb is used for mapping the corresponding path in the feature file. Feature file will have the scenarios in plain english. The
After setting the environment we need to create a feature file. That is, we can use cucumber generator for generating feature
$ rails g cucumber:feature user email:string password:string confirm_password:string
It is generally recommended that you do not create feature by using generators. It's better to write your own feature file. It will help you to define the scenarios on your own and helps in turn in implementing step definitions for the scenarios.
Let us consider an example. I am going to test the signup feature for my application. Since it's generic for any application, I took this as an example.
First we are going to describe the behavior in plain text. That is, create a feature file for signup. In this example, I am going to test one scenario while signing up. The user enters input in the following fields-e-mail, password and password confirmation. If the input in password and password confirmation fields do not match, an error message should be displayed. I am going to write a test case for this.
#sign_up.feature Feature: Sign up As an unauthorized user I want to signup with my details So that I can login Scenario: Password doesn't match confirmation Given I am on the signup page When I fill in "Email" with "firstname.lastname@example.org" And I fill in "Password" with "Secret" And I fill in "Password confirmation" with "Password" And I press "Sign Up" Then the Sign up form should be shown again And I should see "Password doesn't match confirmation" And I should not be registered
Next we need to run the features by the following command:
#To run full test suite $ rake cucumber #To run a single feature $ cucumber features/signup.feature
When you run the above command, you will get the following output in your console:
$ cucumber features/sign_up.feature Using the default profile... F------- (::) failed steps (::) Can't find mapping from "the "signup" page" to a path. Now, go and add a mapping in /home/manivannan/myproj/Projects/test/features/support/paths.rb (RuntimeError) ./features/support/paths.rb:36:in `rescue in path_to' ./features/support/paths.rb:30:in `path_to' ./features/step_definitions/web_steps.rb:20:in `/^(?:|I )am on (.+)$/' features/sign_up.feature:7:in `Given I am on the "/signup" page' Failing Scenarios: cucumber features/sign_up.feature:6 # Scenario: Password doesn't match confirmation 1 scenario (1 failed) 8 steps (1 failed, 7 skipped) 0m0.362s
The output is usually color coded to indicate failures. Now we need to map the corresponding path in paths.rb. It looks like as follows,
#paths.rb when /signup/ new_user_registration_path
I had used devise (ruby gem) for signup, and so I give the corresponding path. new_user_registration_path is generated when I use devise_for:users in the routes file.
After mapping the path, run the feature again as follows:
$ cucumber features/signup.feature Using the default profile... .....U-U 1 scenario (1 undefined) 8 steps (1 skipped, 2 undefined, 5 passed) 0m2.295s You can implement step definitions for undefined steps with these snippets: Then /^the Sign up form should be shown again$/ do pending # express the regexp above with the code you wish you had end Then /^I should not be registered$/ do pending # express the regexp above with the code you wish you had end
It will indicate the undefined steps for your feature. You just need to copy and paste it in the step definition file for signup feature. This is how my step definition file looks.
#sign_up.rb Then /^the Sign up form should be shown again$/ do get "users/new" end Then /^I should not be registered$/ do assert_nil User.find_by_email("email@example.com") end
Now run the test again,
$ cucumber features/sign_up.feature Using the default profile... ........ 1 scenario (1 passed) 8 steps (8 passed) 0m1.477s
Now you can see that all the tests have passed. Hurray!