Posted in Knowledge
Cucumber allow us to describe behavior in plain text. Because the text is written in a business-readable domain-specific language, beside serves as automated tests and development-aid, it also can be used as documentation. In this post we’re going to create a Rails application from scratch, and use Cucumber to define its behaviour.
Install Cucumber, Webrat and RSpec
If you’re happen to be a Ubuntu/Debian user then you need to install Nokogiri first. Nokogiri is an HTML, XML, SAX, and Reader parser. We’re gonna use Webrat in the Step Definition, so we’ll have to use have it installed too.gem install rspec rspec-rails cucumber webratsatisfy plugin dependencies
gem install term-ansicolor treetop diff-lcs nokogiri builder
Creating The Application
We’ll start by creating a new Rails application and for the purposes of this example we’re going to use the classic example and create a todos list app. To start we’ll create the application in the usual way:
rails todos
and create the corresponding databases. Now go to your application directory and set up Cucumber with
ruby script/generate cucumber
command you just entered will generate a features directory under your application’s root directory and it’s here where we’ll define our application’s behavior.
Creating a Feature
We are creating a todos list application in order to manage our never ending todos list, so let’s create a file called manage_todos.feature in the features directory.
Feature: Manage Todos In order to make a todos listAs an userI want to create and manage todos
Now still on the same file, we’ll define some of the feature’s behaviour by writing one (or more scenario)
Scenario: Todos List Given I have todos titled Breakfast, Go to the Office When I go to the todos list Then I should see "Breakfast" And I should see "Go to the Office"
now you can run Cucumber with
cucumber features/manage_todos.feature -n
You’ll see from the results of running the scenario, 3 of the steps were skipped and on is marked as undefined. Now let’s write the Ruby code to implement it.
Step Definitions
Create a file called todos_steps.rb in the features/step_definitions directory, this is where we’ll define our scenario. The scenario
Given I have todos titled Breakfast, Go to the Office
will implement this step definition
Given /^I have todos titled (.+)$/ do |titles| titles.split(', ').each do |title| Todo.create(:title => title) endend
after adding the above code to todos_steps.rb, try to run Cucumber again and watch it fail because the we don’t have a Todo model. Now let’s code the Todo model and since we’re using RSpec, we’re gonna use RSpec generator to create it
ruby script/generate rspec_model Todo title:string is_done:boolean
and run the migration. Now run Cucumber again and you will see that we passed the first step but the second is fail. Let’s create the path of “the todos list” by adding
when /the todos list/ todos_path
in the features/support/paths.rb then add this in file routes.rb
map.resources :todos
when you run Cucumber at this point, you will see error message:
uninitialized constant TodosController (NameError)
Now let’s create the controller
ruby script/generate rspec_controller todos index
when you run Cucumber again, you will see that Cucumber isn’t satisfied enough, it expects to see “Breakfast”. Let’s open the controller and make sure it now show the todos list
def index @todos = Todo.all end
and for the viewNow run the Cucumber again then you will see all the steps passed.
Selenium integrated with Webrat
We are going to integrate Selenium with Webrat. We’ll start with installing Selenium gem
sudo gem install selenium
Now to install Selenium Remote you must download selenium-remote-control first from http://selenium.org/download. Extract and find selenium-jar then copy the file to GEM_INSTALL_DIR/Selenium-1.1.14/lib/selenium/openqa/ and rename it to selenium-server.jar.txtIf you happen to use Ubuntu you have create a sym link due to a bug with Selenium and Firefox 3
sudo ln -s /usr/lib/firefox-3.0.9/firefox /usr/bin/firefox-bin
Now you can start Selenium with
selenium
We can start to make Cucumber / Selenium / Webrat to be integrated. It’s done because many apps have features that don’t require javascript to work, and running them all in selenium makes things slow. Here the solutions :
- Run your non-selenium features with transactional fixtures and standard Webrat steps
- Run your entire suite (html and javascript) features with selenium, without transactional fixtures
- Reuse all (or almost all) or your step definitions between selenium and non-selenium runners
First, setup a directory structure like this you will have the following in the features directory
.|-- enchanced |-- manage_todos.feature |-- plain |-- step_definitions | |-- todos_steps.rb | `-- webrat_steps.rb `-- support |-- env.rb `-- paths.rb
then create a cucumber.yml with 2 profiles in your application root directory thet contains
default: -r features/support/env.rb -r features/support/plain.rb -r features/step_definitions features/plainselenium: -r features/support/env.rb -r features/support/enhanced.rb -r features/step_definitions features/enhanced
turn on all webrat features in env.rb
ENV["RAILS_ENV"] = "test" require File.expand_path(File.dirname(__FILE__) + '/../../config/environment')require 'cucumber/rails/world'require 'cucumber/formatters/unicode'require 'webrat/rails'require 'cucumber/rails/rspec'
then in plain.rb we set up the standard Webrat features
Cucumber::Rails.use_transactional_fixtures
now try to run you Selenium features with
cucmber -p selenium
Using fixtures in cucumber
To use fixtures in cucumber, first you want to add the following to env.rb
Before do Fixtures.reset_cachefixtures_folder = File.join(RAILS_ROOT, 'spec', 'fixtures') fixtures = Dir[File.join(fixtures_folder, '*.yml')].map {|f| File.basename(f, '.yml') } Fixtures.create_fixtures(fixtures_folder, fixtures)end
create fixture files in directory /spec/fixtures/
spec/|-- fixtures| `-- todos.yml
you easily use fixture using Model.find(). Lets add some todos to todos.yml
one: title: Go home is_done: falsetwo: title: Get some sleep is_done: false
Then add this following scenario to manage_todos.feature
Scenario: Todos List from fixture Given I have some todos When I go to the todos list Then I should see "Go home" And I should see "Get some sleep"
and for todos_steps.rb we add this
Given /^I have some todos$/ do Todo.find(:all)end
You can now run cucumber and see your test passed.Well that’s folks, since this post covered only the basics of Cucumber but we hope it is enough for you to get started with.