quality code with cucumber presentation

61
Aslak Hellesøy - Chief Scientist http://cukes.info/ twitter.com/aslak_hellesoy [email protected]

Upload: railsconf

Post on 14-May-2015

2.752 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: Quality Code With Cucumber Presentation

Aslak Hellesøy - Chief Scientist

http://cukes.info/

twitter.com/[email protected]

Page 4: Quality Code With Cucumber Presentation

THIS IS REALLY BAD NEWS!!

http://www.flickr.com/photos/jelles/2656101758/

Page 5: Quality Code With Cucumber Presentation

85 committers989 github followers 33000 gem downloads 30 related tools

http://www.flickr.com/photos/twose/887903401/

Page 6: Quality Code With Cucumber Presentation

http://www.flickr.com/photos/purrr/126597849/

It’s testing crack. One serious stab at using it and I'm hooked.

Page 7: Quality Code With Cucumber Presentation

featuresstep_definitions

supportenv.rb

webrat_steps.rb

paths.rb

Installing Cucumber$ gem install cucumber webrat rspec-rails rspec$ script/generate cucumber

Page 8: Quality Code With Cucumber Presentation

ENV["RAILS_ENV"] ||= "test"require File.expand_path(File.dirname(__FILE__) + '/../../config/environment')require 'cucumber/rails/world'require 'cucumber/formatter/unicode'Cucumber::Rails.use_transactional_fixturesCucumber::Rails.bypass_rescue

# Plus some more setup stuff.....

env.rb

Page 9: Quality Code With Cucumber Presentation

webrat_steps.rbGiven /^I am on (.+)$/ do |page_name| visit path_to(page_name)end

When /^I press "([^\"]*)"$/ do |button| click_button(button)end

Then /^I should see "([^\"]*)"$/ do |text| response.should contain(text)end

Page 10: Quality Code With Cucumber Presentation

module NavigationHelpers # When /^I go to (.+)$/ do |page_name| def path_to(page_name) case page_name when /the homepage/ '/' when /^(.*)'s profile page$/i user_profile_path(User.find_by_login($1)) else raise "Can't find mapping for \"#{page_name}\"" end endend

World(NavigationHelpers)

paths.rb

Page 11: Quality Code With Cucumber Presentation

Outside-In

Page 12: Quality Code With Cucumber Presentation
Page 13: Quality Code With Cucumber Presentation

Proposal notification

In order to reduce time spent on emailing

Administrators should be able to

mail proposal status to all owners

Page 14: Quality Code With Cucumber Presentation

GivenWhen

Then

Page 15: Quality Code With Cucumber Presentation

Feature: Proposal notification In order to reduce time spent on emailing Administrators should be able to mail all proposals owners depending on status Scenario: Email accepted proposal Given [email protected] proposed Cucumber And the Cucumber proposal is approved When I send proposal emails Then [email protected] should get email """ Hi [email protected] Congratulations, Cucumber was accepted. See you at RailsConf! """

Our First Feature

features/proposal_notification.feature

Page 16: Quality Code With Cucumber Presentation

$ cucumber features/proposal_notification.feature

Run the feature

Page 17: Quality Code With Cucumber Presentation

Feature: Proposal notification In order to reduce time spent on emailing Administrators should be able to mail all proposals owners depending on status

Scenario: Email accepted proposal Given [email protected] proposed Cucumber And the Cucumber proposal is approved When I send proposal emails Then [email protected] should get email """ Hi [email protected] Congratulations, Cucumber was accepted. See you at RailsConf! """

1 scenario (1 undefined)4 steps (4 undefined)

Page 18: Quality Code With Cucumber Presentation

Feature: Proposal notification In order to reduce time spent on emailing Administrators should be able to mail all proposals owners depending on status

Scenario: Email accepted proposal Given [email protected] proposed Cucumber And the Cucumber proposal is approved When I send proposal emails Then [email protected] should get email """ Hi [email protected] Congratulations, Cucumber was accepted. See you at RailsConf! """

1 scenario (1 undefined)4 steps (4 undefined)

Page 19: Quality Code With Cucumber Presentation

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

Given /^aslak\.hellesoy@gmail\.com proposed Cucumber$/ do pendingend

Given /^the Cucumber proposal is approved$/ do pendingend

When /^I send proposal emails$/ do pendingend

Then /^aslak\.hellesoy@gmail\.com should get email$/ do |string| pendingend

Page 20: Quality Code With Cucumber Presentation

Given /^aslak\.hellesoy@gmail\.com proposed Cucumber$/ do pendingend

Given /^the Cucumber proposal is approved$/ do pendingend

When /^I send proposal emails$/ do pendingend

Then /^aslak\.hellesoy@gmail\.com should get email$/ do |string| pendingend

Step Definitions

features/step_definitions/proposal_steps.rb

Page 21: Quality Code With Cucumber Presentation

features

step_definitions

supportenv.rb

proposal_steps.rb

paths.rb

webrat_steps.rb

proposal_n..n.feature

Page 22: Quality Code With Cucumber Presentation

Feature: Proposal notification In order to reduce time spent on emailing Administrators should be able to mail all proposals owners depending on status

Scenario: Email accepted proposal Given [email protected] proposed Cucumber TODO (Cucumber::Pending) features/step_definitions/proposal_steps.rb:2 features/proposal_notification.feature:7 And the Cucumber proposal is approved When I send proposal emails Then [email protected] should get email """ Hi [email protected] Congratulations, Cucumber was accepted. See you at RailsConf! """

Page 23: Quality Code With Cucumber Presentation

Given /^aslak\.hellesoy@gmail\.com proposed Cucumber$/ do Proposal.create!({ :email => '[email protected]', :title => 'Cucumber' })end

Do what Regexp says

features/step_definitions/proposal_steps.rb

Page 24: Quality Code With Cucumber Presentation

Feature: Proposal notification In order to reduce time spent on emailing Administrators should be able to mail all proposals owners depending on status

Scenario: Email accepted proposal Given [email protected] proposed Cucumber uninitialized constant Proposal (NameError) features/step_definitions/proposal_steps.rb:2 features/proposal_notification.feature:7 And the Cucumber proposal is approved When I send proposal emails Then [email protected] should get email """ Hi [email protected] Congratulations, Cucumber was accepted. See you at RailsConf! """

Page 25: Quality Code With Cucumber Presentation

$ script/generate rspec_scaffold proposal \ email:string title:string approved:boolean

$ rake db:migrate db:test:clone

$ cucumber features --no-source

Make it Pass

Page 26: Quality Code With Cucumber Presentation

Feature: Proposal notification In order to reduce time spent on emailing Administrators should be able to mail all proposals owners depending on status

Scenario: Email accepted proposal Given [email protected] proposed Cucumber And the Cucumber proposal is approved TODO (Cucumber::Pending) features/step_definitions/proposal_steps.rb:9 features/proposal_notification.feature:8 When I send proposal emails Then [email protected] should get email """ Hi [email protected] Congratulations, Cucumber was accepted. See you at RailsConf! """

Page 27: Quality Code With Cucumber Presentation

Given /^the Cucumber proposal is approved$/ do proposal = Proposal.find_by_title('Cucumber') proposal.approved = true proposal.save!end

Implement Intention

features/step_definitions/proposal_steps.rb

Page 28: Quality Code With Cucumber Presentation

Feature: Proposal notification In order to reduce time spent on emailing Administrators should be able to mail all proposals owners depending on status

Scenario: Email accepted proposal Given [email protected] proposed Cucumber And the Cucumber proposal is approved When I send proposal emails TODO (Cucumber::Pending) features/step_definitions/proposal_steps.rb:15 features/proposal_notification.feature:9 Then [email protected] should get email """ Hi [email protected] Congratulations, Cucumber was accepted. See you at RailsConf! """

Page 29: Quality Code With Cucumber Presentation

When /^I send mass proposal email$/ do visit(’admin’) click_button("Send proposal emails")end

Webrat

Page 30: Quality Code With Cucumber Presentation

Feature: Proposal notification In order to reduce time spent on emailing Administrators should be able to mail all proposals owners depending on status

Scenario: Email accepted proposal Given [email protected] proposed Cucumber And the Cucumber proposal is approved When I send mass proposal email No route matches "/admin" with {:method=>:get} features/step_definitions/proposal_steps.rb:16 features/proposal_notification.feature:9 Then [email protected] should get email """ Hi [email protected] Congratulations, Cucumber was accepted. See you at RailsConf! """

Page 31: Quality Code With Cucumber Presentation
Page 32: Quality Code With Cucumber Presentation

Add the Controllerclass AdminController < ApplicationController def index endend

Page 33: Quality Code With Cucumber Presentation

Feature: Proposal notification In order to reduce time spent on emailing Administrators should be able to mail all proposals owners depending on status

Scenario: Email accepted proposal Given [email protected] proposed Cucumber And the Cucumber proposal is approved When I send mass proposal email Could not find link "Send proposal emails" features/step_definitions/proposal_steps.rb:16 features/proposal_notification.feature:9 Then [email protected] should get email """ Hi [email protected] Congratulations, Cucumber was accepted. See you at RailsConf! """

Page 34: Quality Code With Cucumber Presentation

Add the link<%= link_to("Send proposal emails", :action => 'mass_email') %>

Page 35: Quality Code With Cucumber Presentation

And #mass_emailclass AdminController < ApplicationController def index end

def mass_email endend

Page 36: Quality Code With Cucumber Presentation

Feature: Proposal notification In order to reduce time spent on emailing Administrators should be able to mail all proposals owners depending on status

Scenario: Email accepted proposal Given [email protected] proposed Cucumber And the Cucumber proposal is approved When I send mass proposal email Then [email protected] should get email """ Hi [email protected] Congratulations, Cucumber was accepted. See you at RailsConf! """

Page 37: Quality Code With Cucumber Presentation

Email-SpecThen /^... should get email$/ do |body| open_email('[email protected]') current_email.body.should == body end

Page 38: Quality Code With Cucumber Presentation

class AdminController < ApplicationController def index end

def mass_email approved = Proposal.find_all_by_approved(true) approved.each do |proposal| AdminMailer.deliver_notification_email(proposal) end endend

Controller

Page 39: Quality Code With Cucumber Presentation

class AdminMailer < ActionMailer::Base def notification_email(proposal) recipients proposal.email from "[email protected]" subject "Your Railsconf proposal" body :proposal => proposal endend

Mailer

Page 40: Quality Code With Cucumber Presentation

Hi <%= @proposal.email %>Congratulations, <%= @proposal.title %> was accepted.See you at RailsConf!

Mailer template

Page 41: Quality Code With Cucumber Presentation

Feature: Proposal notification In order to reduce time spent on emailing Administrators should be able to mail all proposals owners depending on status

Scenario: Email accepted proposal Given [email protected] proposed Cucumber And the Cucumber proposal is approved When I send mass proposal email Then [email protected] should get email """ Hi [email protected] Congratulations, Cucumber was accepted. See you at RailsConf! """

Page 42: Quality Code With Cucumber Presentation

Scenarios? Steps?

Page 43: Quality Code With Cucumber Presentation

Steps & Step Definitions

Given [email protected] proposed Cucumber

Given /^aslak\.hellesoy@gmail\.com proposed Cucumber$/ doend

Step == Method invocation

Step Definition == Method defnition

Page 44: Quality Code With Cucumber Presentation

Regexp group arguments

Given [email protected] proposed Cucumber

Given /^(.+) proposed (.+)$/ do |email, proposal_name|end

Given [email protected] proposed Cucumber

$CUCUMBER_COLORS

Page 45: Quality Code With Cucumber Presentation

Quoted arguments

Given I have "22" cukes in my belly

Given /^I have "([^\"]*)" cukes in my belly$/ do |n|end

Given I have "2" cukes in my belly

Page 46: Quality Code With Cucumber Presentation

Multiline args (String)Then [email protected] should get email """ Hi [email protected] Congratulations, Cucumber was accepted. See you at RailsConf! """

Then /^(.+) should get email$/ do |email, body|end

Page 47: Quality Code With Cucumber Presentation

Multiline args (Tables)Given the following proposals | email | title | | [email protected] | Cucumber | | [email protected] | Webrat |

Given /the following proposals$/ do |proposals| Proposal.create!(proposals.hashes)end

Page 48: Quality Code With Cucumber Presentation

Scenario Outline: Email accepted proposals Given the following proposals | email | title | | [email protected] | Cucumber | | [email protected] | Webrat | And the <proposal> proposal is approved When I send proposal emails Then <email> should <what>

Examples: | proposal | email | what | | Cucumber | [email protected] | get email | | Cucumber | [email protected] | not get email | | Webrat | [email protected] | get email |

Scenario Outline

Page 49: Quality Code With Cucumber Presentation

OH HAI: STUFFING

MISHUN: CUCUMBR I CAN HAZ IN TEH BEGINNIN 3 CUCUMBRZ WEN I EAT 2 CUCUMBRZ DEN I HAZ 2 CUCUMBERZ IN MAH BELLY AN IN TEH END 1 CUCUMBRZ KTHXBAI

$ cucumber -l en-lol stuffing.feature

Page 50: Quality Code With Cucumber Presentation

AIL WITH STYLF E

Page 51: Quality Code With Cucumber Presentation

Then /^I should have "(\d+)" cukes my belly$/ do |cukes| @belly.cukes.length.should == cukes.to_iend

RSpec

Then /^I should have "(\d+)" cukes my belly$/ do |cukes| @belly.should have(cukes.to_i).cukesend

Kosher RSpec

Then /^I should have "(\d+)" cukes my belly$/ do |cukes| assert_equal(@cukes.to_i, @belly.cukes.length)end

Test::Unit

Page 52: Quality Code With Cucumber Presentation

Line numbersThen bla bla # features/step_definitions/bla_steps.rb:16

Page 53: Quality Code With Cucumber Presentation

Stack tracesWhen I send mass proposal email Could not find link "Send proposal emails" features/step_definitions/proposal_steps.rb:16 features/notification.feature:9

$ cucumber features/notifications.rb:9

Page 54: Quality Code With Cucumber Presentation

HooksBefore doend

After do |scenario|end

World doend

World(MyModule)World(HerModule)

support/hooks.rb or support/env.rb

Page 55: Quality Code With Cucumber Presentation

Feature: Notification emails Background: Given the following proposals | email | title | | [email protected] | Cucumber | | [email protected] | Webrat |

Scenario: Approved

Background: Rejected

Background

Page 56: Quality Code With Cucumber Presentation

Tagged HooksBefore('@im_special', '@me_too') do @icecream = trueend

@me_tooFeature: Lorem Scenario: Ipsum Scenario: Dolor

Feature: Sit @im_special Scenario: Amet Scenario: Consec

Page 57: Quality Code With Cucumber Presentation

Feature: Take over the world I want it all

@spanish @french @english Scenario: Take over Europe @spanish @english Scenario: Take over America

@english Scenario: Take over Australia

cucumber -t spanish doit.featurecucumber -t ~french doit.feature

Tagged Execution

Page 58: Quality Code With Cucumber Presentation

What’sinside?

Page 59: Quality Code With Cucumber Presentation

a.featureb.feature

x_steps.rby_steps.rb

YourCode

RSpec/Test::Unit/Shoulda

Page 60: Quality Code With Cucumber Presentation

Not doing Rails?

Page 61: Quality Code With Cucumber Presentation