Skip to content

Latest commit

 

History

History
510 lines (310 loc) · 13 KB

README.textile

File metadata and controls

510 lines (310 loc) · 13 KB

Project was generated from rails3-devise-rspec-cucumber-template with some modifications to get by a couple of errors caused by edge rails.
rails new deals -m https://raw.github.com/RailsApps/rails3-application-templates/master/rails3-devise-rspec-cucumber-template.rb -T

Clone Project

git clone git@github.com:jspooner/Deals-BDD-Example.git
switch to tag

update database.yml.template
update gem file for sqlite or mysql

$ bundle install
$ rake db:create
$ rake db:migrate
$ RAILS_ENV=test rake db:migrate
$ rake db:seed

rake cucumber:wip
2 scenarios (2 failed)
15 steps (2 failed, 8 skipped, 1 undefined, 4 passed)
0m1.388s

You can implement step definitions for undefined steps with these snippets:

Then /^the deal should be saved$/ do
pending # express the regexp above with the code you wish you had
end

Implement Step Definitions

$ touch /features/step_definitions/deal_steps.rb

Then /^the deal should be saved$/ do
pending # express the regexp above with the code you wish you had
end

rake cucumber:wip

p. Ok let’s make this pass

Can’t find mapping from “the new deal page” to a path.
Now, go and add a mapping in /Users/jonathanspooner/Dropbox/active/bdd/deals/features/support/paths.rb (RuntimeError)

p. We don’t need to add anything to paths.rb because we can just use the catch all path.

begin
page_name =~ /the (.*) page/

rescue Object => e
raise “Can’t find mapping from \”#{page_name}\" to a path.\n" +
“Now, go and add a mapping in #{__FILE__}”
end

h3. Let’s make the mapping work for “the new deal page”

routes.rb
resources :deals

and run rake cucumber:wip

Scenario: Create a new deal # features/deals/create_deals.feature:12
Given I am on the new deal page # features/step_definitions/web_steps.rb:44
uninitialized constant DealsController (ActionController::RoutingError)
./features/step_definitions/web_steps.rb:45:in `/^(?:|I )am on (.+)$/’
features/deals/create_deals.feature:13:in `Given I am on the new deal page’

p. Now the mapping works and cucumber is driving the next step. It wants a DealsController!

Generate the DealsController

Okay let’s cheat a little and use a rails generator to speed things up.
BDD want’s us todo this
* rails g controller Deals new
* rake cucumber:wip
* RED When I fill in “Title” with “Mega skateboard deals”
* Add form to new.html
* rake cucumber:wip
* RED And I press “Create Deal”
* Add DealsController#create

This would be the right method with a very custom feature but this one is SUPER basic so we’ll skip a few steps and use the scaffold generator.

* be rails g scaffold deals title:string start_date:datetime end_date:datetime quantity:integer description:text number_sold:integer

h4. No let’s drop a down a gear and take a look at our specs.

* Add default value for number_sold in 20110823170906_create_deals.rb
* Add a spec for our default values.

/spec/models/deal_spec.rb
describe “init” do
it { Deal.new.number_sold.should eql(0) }
it { Deal.new.quantity.should eql(0) }
end

then add default values to 20110823170906_create_deals.rb t.integer :quantity, :default => 0 t.integer :number_sold, :default => 0

* rake db:migrate
* RAILS_ENV=test rake db:migrate
* rake spec

h4. Look at the deals_controller_spec

* rake spec:controllers

* Let’s use FactoryGirl to make our lives easier later.
* Why FactoryGirl?

/spec/factory.rb
Factory.define :deal do |d|
d.title ‘Mega Skateboard deal’
d.start_date (Date.today-5).to_date
d.end_date (Date.today+5).to_date
d.description ‘Mega ramp skateboard by Jake Brown is on sale.’
d.quantity 100
d.number_sold 0
end

/spec/controllers/deals_controller_spec.rb
* “deal = Deal.create! valid_attributes” and replace with “deal = Factory(:deal)”

Update valid_attributes to use FactoryGirl

def valid_attributes
{}
end

def valid_attributes
Factory.attributes_for(:deal)
end

* rake spec – Everything should be green
* now back to the BDD cycle

  • rake spec:controllers

rake cucumber:wip

When I fill in “Start date” with “2011/9/1”
cannot fill in, no text field, text area or password field with id, name, or label ‘Start date’ found (Capybara::ElementNotFound)

The rails generator by default gives us select boxes but we want a text_field.

We’ll update datetime_select with text_field for start_date and end_date.

rake cucumber:wip

Then the deal should be saved
TODO (Cucumber::Pending)
./features/step_definitions/deal_steps.rb:2:in `/^the deal should be saved$/’
features/deals/create_deals.feature:19:in `Then the deal should be saved’

Let’s implement this step definition

/features/step_definitions/deal_steps.rb
Then /^the deal should be saved$/ do
page.should have_content(“Deal was successfully created.”)
end

rake cucumber:wip

Looks Green!
Scenario: Create a new deal
Given I am on the new deal page
When I fill in “Title” with “Mega skateboard deals”
When I fill in “Start date” with “2011/9/1”
When I fill in “End date” with “2011/9/1”
When I fill in “Quantity” with “1000”
And I press “Create Deal”
Then the deal should be saved
Then I should see “Mega skateboard deals”

Now let’s move our @wip tag down and fix this “title can’t be blank error”

Then I should see “Title can’t be blank”

Looks like this should be valid so let’s drop down a gear and update the Deal model.

specs/models/deal_spec.rb

describe “validation” do
it { Deal.new.should have(1).errors_on(:title) }
end

rake spec:models

Deal validation
Failure/Error: it { Deal.new.should have(1).errors_on(:title) }
expected 1 errors on :title, got 0

  1. ./spec/models/deal_spec.rb:9:in `block (3 levels) in <top (required)>’

Deal.rb

validates_presence_of :title

rake spec:models

Finished in 1.73 seconds
16 examples, 0 failures

Looking Green! Let’s go back up to Cucumber.

rake cucumber:wip

The —wip switch was used, so I didn’t expect anything to pass. These scenarios passed:
(::) passed scenarios (::)

Let’s remove that @wip tag from the .feature file

rake cucumber

Looks good. Time to commit and move on to the home_page.feature

  • Move @wip from completed steps.
  • add @wip to home_steps.rb

HOME PAGE

rake cucumber:wip

Let’s implement some step definitions.

  • create /features/step_definitions/home_steps.rb
  • add @wip tag to home_page.feature

rake cucumber:wip

Background:
Given there are 4 past 4 current and 2 future deals # features/step_definitions/home_steps.rb:1
TODO (Cucumber::Pending)
./features/step_definitions/home_steps.rb:2:in `/^there are (\d+) past (\d+) current and (\d+) future deals$/’
features/home/home_page.feature:7:in `Given there are 4 past 4 current and 2 future deals’

Implement background step. “Given there are 4 past 4 current and 2 future deals”

  • variables
  • FactoryGirl

$ touch features/step_definitions/home_steps.rb

  • past these steps
Given /^there are (\d+) past (\d+) current and (\d+) future deals$/ do |past, current, future| past.to_i.times do Factory(:deal, {:start_date => Date.today-30, :end_date => Date.today-20}) end current.to_i.times do Factory(:deal, {:start_date => Date.today-3, :end_date => Date.today+2}) end current.to_i.times do Factory(:deal, {:start_date => Date.today+3, :end_date => Date.today+6}) end end

rake cucumber:wip

Given I am on the home page
Then I should see 4 deals
TODO (Cucumber::Pending)
./features/step_definitions/home_steps.rb:14:in `/^I should see (\d+) deals$/’
features/home/home_page.feature:11:in `Then I should see 4 deals’

Implement step to count deals

Then /^I should see (\d+) deals$/ do |arg1|
page.should have_selector(“div.deal”, :count => arg1)
end

rake cucumber:wip

Scenario: Create a new deal
Given I am on the home page
Then I should see 4 deals
expected css “div.deal” to return something (RSpec::Expectations::ExpectationNotMetError)

Let’s drop down a gear and update the model.

spec/models/deal_spec.rb

Add named scope for current deals.

describe “queries” do
before(:each) do
past = Factory(:deal, { :start_date => 30.days.ago, :end_date => 29.days.ago }) @current = Factory(:deal, { :start_date => 5.days.ago, :end_date => 5.days.from_now }) @future = Factory(:deal, { :start_date => 5.days.from_now, :end_date => 10.days.from_now }) end it "should find current deals" do deals = Deal.current deals.should have(1).item deals.first.should eql(current)
end
end

rake spec:models

Failure/Error: deals = Deal.current
NoMethodError:
undefined method `current’ for #

Let’s add this to app/models/deal.rb
scope :current

rake spec:models

Deal queries should find current deals
Failure/Error: deals.should have(1).item
expected 1 item, got 3

Ok now we need to get the query right.

scope :current, where(“Date(start_date) <= ? AND Date(end_date) >= ?”, Date.today.to_date, Date.today.to_date)

rake spec:models

Finished in 0.1878 seconds
17 examples, 0 failures

REFRACTOR!

We need a lambda around the query so the date isn’t cashed.
scope :current, lambda{ where(“Date(start_date) <= ? AND Date(end_date) >= ?”, Date.today.to_date, Date.today.to_date)}

rake spec:models

Finished in 0.1878 seconds
17 examples, 0 failures

Looks Green! Let’s bounce back up to cucumber.

rake cucumber:wip

Scenario: Create a new deal
Given I am on the home page
Then I should see 4 deals

!We need to display the deals on the home page.

Let’s use our Deal.current in the home_controller

/spec/controllers/home_controller_spec.rb

it “should set the current deals” do
deal = Factory(:deal)
get :index
assigns(:deals).should eq([deal])
end

rake spec:controllers

1) HomeController GET ‘index’ should set the current deals
Failure/Error: assigns(:deals).should eq([deal])

Edit home_controller.rb
@deals = Deal.current

rake spec:controllers

………………..

Finished in 0.42225 seconds
20 examples, 0 failures

rake cucumber:wip

Let’s add some html

open app/views/home/index.html

<% @deals.each do |deal| >


<= deal.title %>

<% end %>

and pop back up to cucumber

rake cucumber:wip

Looks Green! Almost!

The customer actually wants the deals to be linked to the deal page.

Let’s update the step_definition to look for links to /deals/

Then /^I should see (\d+) links to deals$/ do |arg1|
page.should have_selector(“div.deal a[href^=‘/deals/’]”, :count => arg1)
end

rake cucumber:wip

Then I should see 4 links to deals # features/step_definitions/home_steps.rb:13
expected css “div.deal a[href^=‘/deals/’]” to return something (RSpec::Expectations::ExpectationNotMetError)

Let’s add the links

Deals

<% @deals.each do |deal| >


<= link_to deal.title, deal %>

<% end %>

rake cucumber:wip

Looks Green!

Deals

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

More Information

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Required Gems

This application requires this gem:

Dependencies

To use this application, you will need:

  • The Ruby language (version 1.8.7 or 1.9.2)
  • Rails (version 3.0.4 or newer)

Installing the Application

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Getting Started

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Documentation and Support

This is the only documentation.

Issues

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Similar Projects

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Contributing

If you make improvements to this application, please share with others.

  • Fork the project on GitHub.
  • Make your feature addition or bug fix.
  • Commit with Git.
  • Send the author a pull request.

If you add functionality to this application, create an alternative implementation, or build an application that is similar, please contact me and I’ll add a note to the README so that others can find your work.

Credits

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

License

Lorem ipsum dolor sit amet, consectetur adipiscing elit.