Behaviour-Driven Development is about implementing an application by describing its behavior from the perspective of its stakeholders.http://en.wikipedia.org/wiki/Behavior_Driven_Development
# A comment here
Feature: Some terse yet descriptive text of what is desired
In order to realize a named business value
As a explicit system actor
I want to gain some beneficial outcome which furthers the goal
@secretlabel
Scenario: Some determinable business situation
Given some precondition
And some other precondition
When some action by the actor
And some other action
And yet another action
Then some testable outcome is achieved
And something else we can check happens too
Keywords: i18n.yml
"en":
name: English
native: English
feature: Feature
background: Background
scenario: Scenario
scenario_outline: Scenario Outline|Scenario Template
examples: Examples|Scenarios
given: "*|Given"
when: "*|When"
then: "*|Then"
and: "*|And"
but: "*|But"
https://github.com/aslakhellesoy/gherkin/blob/master/lib/gherkin/i18n.yml
"en-lol":
name: LOLCAT
native: LOLCAT
feature: OH HAI
background: B4
scenario: MISHUN
scenario_outline: MISHUN SRSLY
examples: EXAMPLZ
given: "*|I CAN HAZ"
when: "*|WEN"
then: "*|DEN"
and: "*|AN"
but: "*|BUT"
https://github.com/aslakhellesoy/gherkin/blob/master/lib/gherkin/i18n.yml
OH HAI: STUFFING
MISHUN: CUCUMBR
I CAN HAZ IN TEH BEGINNIN 3 CUCUMBRZ
WEN I EAT 2 CUCUMBRZ
DEN I HAS 2 CUCUMBERZ IN MAH BELLY
AN IN TEH END 1 CUCUMBRZ KTHXBAI
# Example feature
Feature: To show how to run cucumber features
Scenario: Simplest scenario
When I go to the homepage
Then I should see "Welcome to Rails"
cucumber features/myfeature.feature
cucumber features
cucumber features/myfeature.feature:3
# Example feature
Feature: To show how to run cucumber features
Scenario: Simplest scenario # features/example.feature:3
Given I am on the homepage # features/step_definitions/steps.rb:1
TODO (Cucumber::Pending)
./features/step_definitions/steps.rb:2:in `/^I am on the homepage$/'
features/example.feature:4:in `Given I am on the homepage'
1 scenario (1 pending)
1 step (1 pending)
0m0.002s
ruby script/generate cucumber --rspec --capybara
# Gemfile
group :test do
gem 'cucumber-rails'
gem 'capybara'
gem 'database_cleaner'
end
rails generate cucumber:install
create config/cucumber.yml
create script/cucumber
create features/step_definitions/web_steps.rb
create features/support
create features/support/paths.rb
create features/support/env.rb
create lib/tasks/cucumber.rake
gsub config/database.yml
https://github.com/aslakhellesoy/cucumber-rails
<%
rerun = File.file?('rerun.txt') ? IO.read('rerun.txt') : ""
rerun_opts = rerun.to_s.strip.empty? ?
"--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} features" :
"--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} #{rerun}"
std_opts = "--format #{ENV['CUCUMBER_FORMAT'] ||
'progress'} --strict --tags ~@wip"
%>
default: <%= std_opts %> features
wip: --tags @wip:3 --wip features
rerun: <%= rerun_opts %> --format rerun --out rerun.txt
--strict --tags ~@wip
https://github.com/aslakhellesoy/cucumber/wiki/cucumber.yml
module NavigationHelpers
def path_to(page_name)
case page_name
when /the home\s?page/
'/'
else
begin
page_name =~ /the (.*) page/
path_components = $1.split(/\s+/)
self.send(path_components.push('path').join('_').to_sym)
rescue Object => e
raise "Can't find mapping from \"#{page_name}\" to a path.\n" +
"Now, go and add a mapping in #{__FILE__}"
end
end
end
end
World(NavigationHelpers)
development:
adapter: sqlite3
database: db/development.sqlite3
pool: 5
timeout: 5000
test: &test
adapter: sqlite3
database: db/test.sqlite3
pool: 5
timeout: 5000
production:
adapter: sqlite3
database: db/production.sqlite3
pool: 5
timeout: 5000
cucumber:
<<: *test
https://github.com/jnicklas/capybara
Given I am on <page_name>
when I go to <page_name>
When I press <button>
When I follow <link>
When I fill in "<field>" with "<value>"
When I fill in "<value>" for "<field>"
When I select "<value>" from "<field>"
When I check "<field>"
When I choose "<field>"
Then I should see "<text>"
Then I should see /<regex>/
Then I should not see "<text>"
Then I should not see /<regex>/
Then the "<field>" field should contain "<value>"
Then the "<label>" checkbox should be checked
Then I should be on <page_name>
Then I should have the following query string <expected_pairs>
Then show me the page
https://github.com/jnicklas/capybara
cucumber features/myfeature.feature
Using the default profile...
..
1 scenario (1 passed)
2 steps (2 passed)
0m0.192s
Factory.define :user do |user|
user.email { Factory.next(:email) }
user.password { "password" }
user.password_confirmation { "password" }
end
Factory.define :author, :parent => :user do |author|
author.after_create { |a| Factory(:article, :author => a) }
end
Factory.define :recruiter, :parent => :user do |recruiter|
recruiter.is_recruiter { true }
end
Given a user exists
Given an author exists with an email of "author@example.com"
Given the following recruiter exists:
| email | phone number | employer name |
| bill@example.com | 1234567890 | thoughtbot |
http://robots.thoughtbot.com/post/284805810/gimme-three-steps
Scenario Outline: eating
Given there are <start> cucumbers
When I eat <eat> cucumbers
Then I should have <left> cucumbers
Examples:
| start | eat | left |
| 12 | 5 | 7 |
| 20 | 5 | 15 |
https://github.com/aslakhellesoy/cucumber/wiki/Scenario-outlines
Feature: Multiple site support
As a Mephisto site owner
I want to host blogs for different people
In order to make gigantic piles of money
Background:
Given a global administrator named "Greg"
And a blog named "Greg's anti-tax rants"
And a customer named "Dr. Bill"
And a blog named "Expensive Therapy" owned by "Dr. Bill"
Scenario: Dr. Bill posts to his own blog
Given I am logged in as Dr. Bill
When I try to post to "Expensive Therapy"
Then I should see "Your article was published."
Scenario: Dr. Bill tries to post to somebody else's blog, and fails
Given I am logged in as Dr. Bill
When I try to post to "Greg's anti-tax rants"
Then I should see "Hey! That's not your blog!"
Scenario: Greg posts to a client's blog
Given I am logged in as Greg
When I try to post to "Expensive Therapy"
Then I should see "Your article was published."
https://github.com/aslakhellesoy/cucumber/wiki/Background
Before do
# Do something before each scenario.
end
After do |scenario|
if(scenario.failed?)
subject = "[Project X] #{scenario.exception.message}"
send_failure_email(subject)
end
end
Around('@fast') do |scenario, block|
Timeout.timeout(0.5) do
block.call
end
end
https://github.com/aslakhellesoy/cucumber/wiki/Hooks
Before('@cucumis,@sativus') do
# This will only run before scenarios tagged
# with @cucumis OR @sativus.
end
Before('@cucumis', '@sativus') do
# This will only run before scenarios tagged
# with @cucumis AND @sativus.
end
Before('@cucumis,@sativus', '@aqua') do
# This will only run before scenarios tagged
# with (@cucumis OR @sativus) AND @aqua
end
my_heavy_object = HeavyObject.new
my_heavy_object.do_it
at_exit do
my_heavy_object.undo_it
end
AfterConfiguration do |config|
puts "Features dwell in #{config.feature_dirs}"
end
Transform /^(-?\d+)$/ do |number|
number.to_i
end
Then /^a user, named "([^']+)", should have (\d+) followers$/ do |name,count|
# Without the transform your count object would be a string
# and not a number
count.should be_kind_of(Numeric)
#...
end
https://github.com/aslakhellesoy/cucumber/wiki/Step-Argument-Transforms
http://drnicwilliams.com/2009/04/15/cucumber-building-a-better-world-object/
class CustomWorld
def a_helper
...
end
end
World do
CustomWorld.new
end
module MyHelper
def some_helper
...
end
end
World MyHelper
https://github.com/aslakhellesoy/cucumber/wiki/A-Whole-New-World
require 'cucumber/rake/task'
Cucumber::Rake::Task.new(:features) do |t|
t.rcov = true
t.rcov_opts = %w{--rails --exclude features,spec,factories,/gems/}
end
https://github.com/aslakhellesoy/cucumber/wiki/Using-RCov-with-Cucumber-and-Rails
Feature "User creates a vurl" do
Scenario "creating" do
Given "I am on the home page" do
executes { visit root_path }
When "I submit a valid vurl" do
executes do
fill_in "vurl_url", :with => 'http://example.com'
click_button 'Vurlify!'
end
Then "I should be on the vurl stats page" do
current_url.should == stats_url(Vurl.last.slug)
end
And "I should see a success message" do
response.body.should include('Vurl was successfully created')
end
And "my vurl was created" do
Vurl.last.url.should == 'http://example.com'
end
end
end
end
end
feature "Main page" do
background do
create_user :login => "jdoe"
login_as "jdoe"
end
scenario "should show existing quotes" do
create_quote :text => "A joke is a very serious thing",
:author => "Winston Churchill"
visit "/"
page.should have_css(".quote", :count => 1)
within(:css, ".quote") do
page.should have_css(".text", :text => "A joke is a very serious thing")
page.should have_css(".author", :text => "Winston Churchill")
end
end
end