Getting Started With Cucumber
12 May 2009
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 dependenciesgem 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 todosand create the corresponding databases. Now go to your application directory and set up Cucumber with
ruby script/generate cucumbercommand 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 todosNow 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 -nYou'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 scenarioGiven I have todos titled Breakfast, Go to the Officewill implement this step definition
Given /^I have todos titled (.+)$/ do |titles| titles.split(', ').each do |title| Todo.create(:title => title) endendafter 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 itruby script/generate rspec_model Todo title:string is_done:booleanand 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_pathin the features/support/paths.rb then add this in file routes.rb
map.resources :todoswhen 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 indexwhen 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 endand 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 gemsudo gem install seleniumNow 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-binNow you can start Selenium with
seleniumWe 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
.|-- enchanced |-- manage_todos.feature |-- plain |-- step_definitions | |-- todos_steps.rb | `-- webrat_steps.rb `-- support |-- env.rb `-- paths.rbthen 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/enhancedturn 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_fixturesnow 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.rbBefore 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)endcreate fixture files in directory /spec/fixtures/spec/|-- fixtures| `-- todos.ymlyou 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: falseThen 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)endYou 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.
