SlideShare a Scribd company logo
1 of 49
Straight Up RSpec
  a neat Ruby BDD tool
The Menu

Organization                 $0

Options                      $0

Refactoring Exercise         $0

Configuration                 $0

Other Libraries              $0
Organization
.rspec
lib/barkeep.rb
lib/barkeep/martini.rb
spec/spec_helper.rb
spec/support/configure.rb
spec/support/matchers/drink.rb
spec/martini_spec.rb
spec_helper
require 'rspec'
require 'barkeep'

Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].
  each {|file| require file }




                                        spec_helper.rb
Options
$ rspec spec -f documentation
$ rspec spec/martini_spec.rb -l 16
$ rspec spec -t slow
Barkeep
github.com/gsterndale/barkeep
   a refactoring exercise
Martini Spec Draft
describe "Barkeep::Martini" do
  before do
    @martini = Barkeep::Martini.new
  end
  it "should have an attribute named booze" do
    @martini.should respond_to(:booze)
    @martini.should respond_to(:booze=)
  end
  it "should have an attribute named garnish" do
    @martini.should respond_to(:garnish)
    @martini.should respond_to(:garnish=)
  end
end

                                       martini_spec.rb
Custom Matcher
module AttributeMatchers

  Spec::Matchers.define :have_attribute do |name|
    match do |target|
      getter = name.to_sym
      setter = (name.to_s + "=").to_sym
      target.respond_to?(getter) &&
        target.respond_to?(setter)
    end
  end

end



                                     have_attribute.rb
Custom Matcher
describe "Barkeep::Martini" do
  include AttributeMatchers
  before do
    @martini = Barkeep::Martini.new
  end
  it "should have an attribute named booze" do
    @martini.should have_attribute(:booze)
  end
  it "should have an attribute named garnish" do
    @martini.should have_attribute(:garnish)
  end
end



                                       martini_spec.rb
subject()
describe "Barkeep::Martini" do
  include AttributeMatchers
  subject { Barkeep::Martini.new }
  it "should have an attribute named booze" do
    subject.should have_attribute(:booze)
  end
  it "should have an attribute named garnish" do
    subject.should have_attribute(:garnish)
  end
end




                                       martini_spec.rb
Implicit subject()
describe "Barkeep::Martini" do
  include AttributeMatchers
  subject { Barkeep::Martini.new }
  it "should have an attribute named booze" do
    should have_attribute(:booze)
  end
  it "should have an attribute named garnish" do
    should have_attribute(:garnish)
  end
end




                                       martini_spec.rb
DRY Messages
describe "Barkeep::Martini" do
  include AttributeMatchers
  subject { Barkeep::Martini.new }
  it { should have_attribute(:booze) }
  it { should have_attribute(:garnish) }
end




                                       martini_spec.rb
Derived subject()
describe Barkeep::Martini do
  include AttributeMatchers
  it { should have_attribute(:booze) }
  it { should have_attribute(:garnish) }
end




                                       martini_spec.rb
config.include()
RSpec.configure do |config|
    config.include AttributeMatchers
end




                                  support/configure.rb
config.include()
describe Barkeep::Martini do
  it { should have_attribute(:booze) }
  it { should have_attribute(:garnish) }
end




                                       martini_spec.rb
Original Draft
describe "Barkeep::Martini" do
  before do
    @martini = Barkeep::Martini.new
  end
  it "should have an attribute named booze" do
    @martini.should respond_to(:booze)
    @martini.should respond_to(:booze=)
  end
  it "should have an attribute named garnish" do
    @martini.should respond_to(:garnish)
    @martini.should respond_to(:garnish=)
  end
end

                                       martini_spec.rb
Whiskey Spec
describe Barkeep::Whiskey do
  it { should have_attribute(:booze) }
  it { should have_attribute(:glass) }
end




                                         whiskey_spec.rb
Martini Spec
describe Barkeep::Martini do
  it { should have_attribute(:booze) }
  it { should have_attribute(:glass) }
  it { should have_attribute(:garnish) }
end




                                       martini_spec.rb
Shared Example Group
share_examples_for "a drink" do
  it { should have_attribute(:booze) }
  it { should have_attribute(:glass) }
end




                             support/examples/drink.rb
Whiskey Spec
describe Barkeep::Whiskey do
  it_should_behave_like "a drink"
end




                                    whiskey_spec.rb
Martini Spec
describe Barkeep::Martini do
  it_should_behave_like "a drink"
  it { should have_attribute(:garnish) }
end




                                       martini_spec.rb
Whiskey & Martini #ingredients
share_examples_for "a drink" do
  it { should have_attribute(:booze) }
  it { should have_attribute(:glass) }

  it "should have an ingredients Array" do
    subject.ingredients.should be_a Array
  end
end




                             support/examples/drink.rb
context()
describe Barkeep::Martini do
  it_should_behave_like "a drink"
  it { should have_attribute(:garnish) }
  it { should have_attribute(:mixer) }
  context "with a mixer" do
    before do
      @mixer        = 'vermouth'
      subject.mixer = @mixer
    end
    it "should include mixer in ingredients" do
      subject.ingredients.should include @mixer
    end
  end

                                       martini_spec.rb
let()
describe Barkeep::Martini do
  it_should_behave_like "a drink"
  it { should have_attribute(:garnish) }
  it { should have_attribute(:mixer) }
  context "with a mixer" do
    let(:mixer) { 'vermouth' }
    before { subject.mixer = mixer }
    it "should include mixer in ingredients" do
      subject.ingredients.should include mixer
    end
  end
end



                                       martini_spec.rb
its()
describe Barkeep::Martini do
  it_should_behave_like "a drink"
  it { should have_attribute(:garnish) }
  it { should have_attribute(:mixer) }
  context "with a mixer" do
    let(:mixer) { 'vermouth' }
    before { subject.mixer = mixer }
    its(:ingredients) { should include mixer }
  end
end




                                       martini_spec.rb
its()
describe Barkeep::Martini do
  it_should_behave_like "a drink"
  it { should have_attribute(:garnish) }
  it { should have_attribute(:mixer) }
end

describe Barkeep::Martini, ".new with mixer" do
  let(:mixer) { 'vermouth' }
  subject { Barkeep::Martini.new(:mixer => mixer) }
  its(:ingredients) { should include mixer }
end




                                       martini_spec.rb
have()
describe Barkeep::Martini, ".new with mixer" do
  let(:mixer) { 'vermouth' }
  subject { Barkeep::Martini.new(:mixer => mixer) }
  its(:ingredients) { should include mixer }
  its(:ingredients) { should have(1).items }
end




                                       martini_spec.rb
have()
describe Barkeep::Martini, ".new with mixer" do
  let(:mixer) { 'vermouth' }
  subject { Barkeep::Martini.new(:mixer => mixer) }
  its(:ingredients) { should include mixer }
  it { should have(1).ingredients }
end




                                       martini_spec.rb
expect()
describe Barkeep::Martini do
  let(:mixer) { 'vermouth' }
  it "should include mixer in ingredients" do
    expect { subject.mixer = mixer }.
    to change { subject.ingredients }.
    from( [] ).
    to [ mixer ]
  end
end




                                       martini_spec.rb
stub()
describe Barkeep::Terminal, "#printer" do
  let(:ones) { "1.1.1.1" }
  let(:epson) { double("Espon 5000") }
  subject { Barkeep::Terminal.new(:ip => ones) }

  before do
    Printer.stub(:new) { epson }
  end

  it "should have a printer" do
    subject.printer.should eq epson
  end
end

                                      terminal_spec.rb
should_receive()
describe Barkeep::Terminal, "#printer" do
  let(:ones) { "1.1.1.1" }
  let(:epson) { double("Espon 5000") }
  subject { Barkeep::Terminal.new(:ip => ones) }

  it "should have a printer" do
    Printer.should_receive(:new).
      with(:ip => ones) { epson }
    subject.printer
  end
end




                                      terminal_spec.rb
Configuration
RSpec.configure
RSpec.configure do |config|
  config.include MyMartiniMatchers
  config.include ModelHelpers, :type => :model
end



# spec/model/martini_spec.rb

describe Martini, :type => :model do
  …
end




                                  support/configure.rb
RSpec.configure
RSpec.configure do |config|
  config.before(:all) {} #    run   once
  config.before(:each) {} #   run   before each example
  config.after (:each) {} #   run   after each example
  config.after (:all) {} #    run   once

  # run before each example of type :model
  config.before(:each, :type => :model) {}
end




                                      support/configure.rb
Inclusion
RSpec.configure do |c|
  c.filter_run :focus => true
  c.run_all_when_everything_filtered = true
end

# in any spec file
describe "something" do
  it "does something", :focus => true do
    # ....
  end
end




                                  support/configure.rb
Exclusion
RSpec.configure do |c|
  c.exclusion_filter = { :ruby => lambda {|version|
     !(RUBY_VERSION.to_s =~ /^#{version.to_s}/)
  }}
end

# in any spec file
describe "something" do
  it "does something", :ruby => 1.8 do
    # ....
  end
  it "does something", :ruby => 1.9 do
    # ....

                                  support/configure.rb
Other Libraries
RSpec::Rails
response.should redirect_to("some/url")
response.should be_success
response.should have_tag("div", "some text")
Shoulda::Matchers
describe User do
  it { should belong_to(:account) }
  it { should have_many(:posts) }
  it { should validate_presence_of(:email) }
  it { should allow_value("f@b.com").for(:email) }
  it { should_not allow_value("test").for(:email) }
end
CHEERS
let() gotcha
describe User, ".admin_names" do
  let(:admin) { User.create!(:admin => true,
    :first => "Clark",
    :last => "Kent")}
  let(:avg_joe) { User.create!(:admin => false,
    :first => "Joe",
    :last => "Shmo")}
  subject { admin_names }

  it { should include "Clark Kent" }
  it { should_not include "Joe Shmo" }
end



                                    spec/user_spec.rb
let() work-around
describe User, ".admin_names" do
  let(:admin) { User.create!(:admin => true,
    :first => "Clark",
    :last => "Kent")}
  let(:avg_joe) { User.create!(:admin => false,
    :first => "Joe",
    :last => "Shmo")}
  subject { User.admin_names }
  before { admin && avg_joe }

  it { should include "Clark Kent" }
  it { should_not include "Joe Shmo" }
end

                                    spec/user_spec.rb
let!()
describe User, ".admin_names" do
  let!(:admin) { User.create!(:admin => true,
    :first => "Clark",
    :last => "Kent")}
  let!(:avg_joe) { User.create!(:admin => false,
    :first => "Joe",
    :last => "Shmo")}
  subject { User.admin_names }

  it { should include "Clark Kent" }
  it { should_not include "Joe Shmo" }
end



                                    spec/user_spec.rb

More Related Content

Viewers also liked

Inaugural quiz-kwizzare
Inaugural quiz-kwizzareInaugural quiz-kwizzare
Inaugural quiz-kwizzarekwizzare
 
KWIZZARE24 FOOD QUIZ
KWIZZARE24 FOOD QUIZKWIZZARE24 FOOD QUIZ
KWIZZARE24 FOOD QUIZkwizzare
 
Kwizzare'15 Grand Finale- MG Quiz
Kwizzare'15 Grand Finale- MG QuizKwizzare'15 Grand Finale- MG Quiz
Kwizzare'15 Grand Finale- MG Quizkwizzare
 
Metaprogramming JavaScript
Metaprogramming  JavaScriptMetaprogramming  JavaScript
Metaprogramming JavaScriptdanwrong
 
The food quiz II with answers
The food quiz II with answersThe food quiz II with answers
The food quiz II with answerssantoshjs
 
Theme quiz (Indian food)
Theme quiz (Indian food)Theme quiz (Indian food)
Theme quiz (Indian food)visweshrammohan
 
Kqa food quiz 2013 prelims
Kqa food quiz 2013 prelimsKqa food quiz 2013 prelims
Kqa food quiz 2013 prelimssantoshjs
 
The food quiz with answers
The food quiz with answersThe food quiz with answers
The food quiz with answerssantoshjs
 
Khana Khazana the food quiz, 2016
Khana Khazana   the food quiz, 2016Khana Khazana   the food quiz, 2016
Khana Khazana the food quiz, 2016Simanta Barman
 
Breakfast and Lunch Recipes from Scotland
Breakfast and Lunch Recipes from ScotlandBreakfast and Lunch Recipes from Scotland
Breakfast and Lunch Recipes from ScotlandTiina Sarisalmi
 
Performance Architecture Manifesto
Performance Architecture ManifestoPerformance Architecture Manifesto
Performance Architecture Manifestosirlegendary
 
All Objects are created .equal?
All Objects are created .equal?All Objects are created .equal?
All Objects are created .equal?gsterndale
 
Library As Teaching Resource
Library As Teaching ResourceLibrary As Teaching Resource
Library As Teaching ResourceBritt Fagerheim
 
Matias Perez Garate
Matias Perez GarateMatias Perez Garate
Matias Perez Garatemapega
 
Refactor like a boss
Refactor like a bossRefactor like a boss
Refactor like a bossgsterndale
 

Viewers also liked (20)

kwizzare
kwizzarekwizzare
kwizzare
 
Inaugural quiz-kwizzare
Inaugural quiz-kwizzareInaugural quiz-kwizzare
Inaugural quiz-kwizzare
 
Food Quiz Key
Food Quiz KeyFood Quiz Key
Food Quiz Key
 
Alcohol awareness quiz
Alcohol awareness quizAlcohol awareness quiz
Alcohol awareness quiz
 
KWIZZARE24 FOOD QUIZ
KWIZZARE24 FOOD QUIZKWIZZARE24 FOOD QUIZ
KWIZZARE24 FOOD QUIZ
 
Kwizzare'15 Grand Finale- MG Quiz
Kwizzare'15 Grand Finale- MG QuizKwizzare'15 Grand Finale- MG Quiz
Kwizzare'15 Grand Finale- MG Quiz
 
Metaprogramming JavaScript
Metaprogramming  JavaScriptMetaprogramming  JavaScript
Metaprogramming JavaScript
 
The food quiz II with answers
The food quiz II with answersThe food quiz II with answers
The food quiz II with answers
 
Theme quiz (Indian food)
Theme quiz (Indian food)Theme quiz (Indian food)
Theme quiz (Indian food)
 
Kqa food quiz 2013 prelims
Kqa food quiz 2013 prelimsKqa food quiz 2013 prelims
Kqa food quiz 2013 prelims
 
The food quiz with answers
The food quiz with answersThe food quiz with answers
The food quiz with answers
 
Khana Khazana the food quiz, 2016
Khana Khazana   the food quiz, 2016Khana Khazana   the food quiz, 2016
Khana Khazana the food quiz, 2016
 
Breakfast and Lunch Recipes from Scotland
Breakfast and Lunch Recipes from ScotlandBreakfast and Lunch Recipes from Scotland
Breakfast and Lunch Recipes from Scotland
 
Performance Architecture Manifesto
Performance Architecture ManifestoPerformance Architecture Manifesto
Performance Architecture Manifesto
 
All Objects are created .equal?
All Objects are created .equal?All Objects are created .equal?
All Objects are created .equal?
 
Lugares
LugaresLugares
Lugares
 
Library As Teaching Resource
Library As Teaching ResourceLibrary As Teaching Resource
Library As Teaching Resource
 
Matias Perez Garate
Matias Perez GarateMatias Perez Garate
Matias Perez Garate
 
Relief 2.0, B2B and Enterprise
Relief 2.0, B2B and EnterpriseRelief 2.0, B2B and Enterprise
Relief 2.0, B2B and Enterprise
 
Refactor like a boss
Refactor like a bossRefactor like a boss
Refactor like a boss
 

Similar to Straight Up RSpec

Ruby on Rails testing with Rspec
Ruby on Rails testing with RspecRuby on Rails testing with Rspec
Ruby on Rails testing with RspecBunlong Van
 
RSpec 1.x -> 2.0 の変更点
RSpec 1.x -> 2.0 の変更点RSpec 1.x -> 2.0 の変更点
RSpec 1.x -> 2.0 の変更点theworldinunion
 
DBIx::Class beginners
DBIx::Class beginnersDBIx::Class beginners
DBIx::Class beginnersleo lapworth
 
TDC 2012 - Patterns e Anti-Patterns em Ruby
TDC 2012 - Patterns e Anti-Patterns em RubyTDC 2012 - Patterns e Anti-Patterns em Ruby
TDC 2012 - Patterns e Anti-Patterns em RubyFabio Akita
 
Making TDD [Somewhat] Bearable on OpenStack
Making TDD [Somewhat] Bearable on OpenStackMaking TDD [Somewhat] Bearable on OpenStack
Making TDD [Somewhat] Bearable on OpenStackHart Hoover
 
Blocks by Lachs Cox
Blocks by Lachs CoxBlocks by Lachs Cox
Blocks by Lachs Coxlachie
 
浜松Rails3道場 其の参 Controller編
浜松Rails3道場 其の参 Controller編浜松Rails3道場 其の参 Controller編
浜松Rails3道場 其の参 Controller編Masakuni Kato
 

Similar to Straight Up RSpec (10)

Ruby on Rails testing with Rspec
Ruby on Rails testing with RspecRuby on Rails testing with Rspec
Ruby on Rails testing with Rspec
 
RSpec 1.x -> 2.0 の変更点
RSpec 1.x -> 2.0 の変更点RSpec 1.x -> 2.0 の変更点
RSpec 1.x -> 2.0 の変更点
 
DBIx::Class beginners
DBIx::Class beginnersDBIx::Class beginners
DBIx::Class beginners
 
TDC 2012 - Patterns e Anti-Patterns em Ruby
TDC 2012 - Patterns e Anti-Patterns em RubyTDC 2012 - Patterns e Anti-Patterns em Ruby
TDC 2012 - Patterns e Anti-Patterns em Ruby
 
Making TDD [Somewhat] Bearable on OpenStack
Making TDD [Somewhat] Bearable on OpenStackMaking TDD [Somewhat] Bearable on OpenStack
Making TDD [Somewhat] Bearable on OpenStack
 
Ruby - Design patterns tdc2011
Ruby - Design patterns tdc2011Ruby - Design patterns tdc2011
Ruby - Design patterns tdc2011
 
Blocks by Lachs Cox
Blocks by Lachs CoxBlocks by Lachs Cox
Blocks by Lachs Cox
 
浜松Rails3道場 其の参 Controller編
浜松Rails3道場 其の参 Controller編浜松Rails3道場 其の参 Controller編
浜松Rails3道場 其の参 Controller編
 
Tres Gemas De Ruby
Tres Gemas De RubyTres Gemas De Ruby
Tres Gemas De Ruby
 
Ruby gems
Ruby gemsRuby gems
Ruby gems
 

Recently uploaded

Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsAndrey Dotsenko
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr LapshynFwdays
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDGMarianaLemus7
 
Unlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power SystemsUnlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power SystemsPrecisely
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions
 
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptxMaking_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptxnull - The Open Security Community
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 

Recently uploaded (20)

Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 
The transition to renewables in India.pdf
The transition to renewables in India.pdfThe transition to renewables in India.pdf
The transition to renewables in India.pdf
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDG
 
Unlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power SystemsUnlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power Systems
 
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort ServiceHot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
Vulnerability_Management_GRC_by Sohang Sengupta.pptx
Vulnerability_Management_GRC_by Sohang Sengupta.pptxVulnerability_Management_GRC_by Sohang Sengupta.pptx
Vulnerability_Management_GRC_by Sohang Sengupta.pptx
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping Elbows
 
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptxMaking_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 

Straight Up RSpec

  • 1. Straight Up RSpec a neat Ruby BDD tool
  • 2. The Menu Organization $0 Options $0 Refactoring Exercise $0 Configuration $0 Other Libraries $0
  • 7. $ rspec spec -f documentation
  • 9. $ rspec spec -t slow
  • 10. Barkeep github.com/gsterndale/barkeep a refactoring exercise
  • 11. Martini Spec Draft describe "Barkeep::Martini" do before do @martini = Barkeep::Martini.new end it "should have an attribute named booze" do @martini.should respond_to(:booze) @martini.should respond_to(:booze=) end it "should have an attribute named garnish" do @martini.should respond_to(:garnish) @martini.should respond_to(:garnish=) end end martini_spec.rb
  • 12. Custom Matcher module AttributeMatchers Spec::Matchers.define :have_attribute do |name| match do |target| getter = name.to_sym setter = (name.to_s + "=").to_sym target.respond_to?(getter) && target.respond_to?(setter) end end end have_attribute.rb
  • 13. Custom Matcher describe "Barkeep::Martini" do include AttributeMatchers before do @martini = Barkeep::Martini.new end it "should have an attribute named booze" do @martini.should have_attribute(:booze) end it "should have an attribute named garnish" do @martini.should have_attribute(:garnish) end end martini_spec.rb
  • 14. subject() describe "Barkeep::Martini" do include AttributeMatchers subject { Barkeep::Martini.new } it "should have an attribute named booze" do subject.should have_attribute(:booze) end it "should have an attribute named garnish" do subject.should have_attribute(:garnish) end end martini_spec.rb
  • 15. Implicit subject() describe "Barkeep::Martini" do include AttributeMatchers subject { Barkeep::Martini.new } it "should have an attribute named booze" do should have_attribute(:booze) end it "should have an attribute named garnish" do should have_attribute(:garnish) end end martini_spec.rb
  • 16. DRY Messages describe "Barkeep::Martini" do include AttributeMatchers subject { Barkeep::Martini.new } it { should have_attribute(:booze) } it { should have_attribute(:garnish) } end martini_spec.rb
  • 17. Derived subject() describe Barkeep::Martini do include AttributeMatchers it { should have_attribute(:booze) } it { should have_attribute(:garnish) } end martini_spec.rb
  • 18. config.include() RSpec.configure do |config| config.include AttributeMatchers end support/configure.rb
  • 19. config.include() describe Barkeep::Martini do it { should have_attribute(:booze) } it { should have_attribute(:garnish) } end martini_spec.rb
  • 20. Original Draft describe "Barkeep::Martini" do before do @martini = Barkeep::Martini.new end it "should have an attribute named booze" do @martini.should respond_to(:booze) @martini.should respond_to(:booze=) end it "should have an attribute named garnish" do @martini.should respond_to(:garnish) @martini.should respond_to(:garnish=) end end martini_spec.rb
  • 21. Whiskey Spec describe Barkeep::Whiskey do it { should have_attribute(:booze) } it { should have_attribute(:glass) } end whiskey_spec.rb
  • 22. Martini Spec describe Barkeep::Martini do it { should have_attribute(:booze) } it { should have_attribute(:glass) } it { should have_attribute(:garnish) } end martini_spec.rb
  • 23. Shared Example Group share_examples_for "a drink" do it { should have_attribute(:booze) } it { should have_attribute(:glass) } end support/examples/drink.rb
  • 24. Whiskey Spec describe Barkeep::Whiskey do it_should_behave_like "a drink" end whiskey_spec.rb
  • 25. Martini Spec describe Barkeep::Martini do it_should_behave_like "a drink" it { should have_attribute(:garnish) } end martini_spec.rb
  • 26. Whiskey & Martini #ingredients share_examples_for "a drink" do it { should have_attribute(:booze) } it { should have_attribute(:glass) } it "should have an ingredients Array" do subject.ingredients.should be_a Array end end support/examples/drink.rb
  • 27. context() describe Barkeep::Martini do it_should_behave_like "a drink" it { should have_attribute(:garnish) } it { should have_attribute(:mixer) } context "with a mixer" do before do @mixer = 'vermouth' subject.mixer = @mixer end it "should include mixer in ingredients" do subject.ingredients.should include @mixer end end martini_spec.rb
  • 28. let() describe Barkeep::Martini do it_should_behave_like "a drink" it { should have_attribute(:garnish) } it { should have_attribute(:mixer) } context "with a mixer" do let(:mixer) { 'vermouth' } before { subject.mixer = mixer } it "should include mixer in ingredients" do subject.ingredients.should include mixer end end end martini_spec.rb
  • 29. its() describe Barkeep::Martini do it_should_behave_like "a drink" it { should have_attribute(:garnish) } it { should have_attribute(:mixer) } context "with a mixer" do let(:mixer) { 'vermouth' } before { subject.mixer = mixer } its(:ingredients) { should include mixer } end end martini_spec.rb
  • 30. its() describe Barkeep::Martini do it_should_behave_like "a drink" it { should have_attribute(:garnish) } it { should have_attribute(:mixer) } end describe Barkeep::Martini, ".new with mixer" do let(:mixer) { 'vermouth' } subject { Barkeep::Martini.new(:mixer => mixer) } its(:ingredients) { should include mixer } end martini_spec.rb
  • 31. have() describe Barkeep::Martini, ".new with mixer" do let(:mixer) { 'vermouth' } subject { Barkeep::Martini.new(:mixer => mixer) } its(:ingredients) { should include mixer } its(:ingredients) { should have(1).items } end martini_spec.rb
  • 32. have() describe Barkeep::Martini, ".new with mixer" do let(:mixer) { 'vermouth' } subject { Barkeep::Martini.new(:mixer => mixer) } its(:ingredients) { should include mixer } it { should have(1).ingredients } end martini_spec.rb
  • 33. expect() describe Barkeep::Martini do let(:mixer) { 'vermouth' } it "should include mixer in ingredients" do expect { subject.mixer = mixer }. to change { subject.ingredients }. from( [] ). to [ mixer ] end end martini_spec.rb
  • 34. stub() describe Barkeep::Terminal, "#printer" do let(:ones) { "1.1.1.1" } let(:epson) { double("Espon 5000") } subject { Barkeep::Terminal.new(:ip => ones) } before do Printer.stub(:new) { epson } end it "should have a printer" do subject.printer.should eq epson end end terminal_spec.rb
  • 35. should_receive() describe Barkeep::Terminal, "#printer" do let(:ones) { "1.1.1.1" } let(:epson) { double("Espon 5000") } subject { Barkeep::Terminal.new(:ip => ones) } it "should have a printer" do Printer.should_receive(:new). with(:ip => ones) { epson } subject.printer end end terminal_spec.rb
  • 37. RSpec.configure RSpec.configure do |config| config.include MyMartiniMatchers config.include ModelHelpers, :type => :model end # spec/model/martini_spec.rb describe Martini, :type => :model do … end support/configure.rb
  • 38. RSpec.configure RSpec.configure do |config| config.before(:all) {} # run once config.before(:each) {} # run before each example config.after (:each) {} # run after each example config.after (:all) {} # run once # run before each example of type :model config.before(:each, :type => :model) {} end support/configure.rb
  • 39. Inclusion RSpec.configure do |c| c.filter_run :focus => true c.run_all_when_everything_filtered = true end # in any spec file describe "something" do it "does something", :focus => true do # .... end end support/configure.rb
  • 40. Exclusion RSpec.configure do |c| c.exclusion_filter = { :ruby => lambda {|version| !(RUBY_VERSION.to_s =~ /^#{version.to_s}/) }} end # in any spec file describe "something" do it "does something", :ruby => 1.8 do # .... end it "does something", :ruby => 1.9 do # .... support/configure.rb
  • 45. describe User do it { should belong_to(:account) } it { should have_many(:posts) } it { should validate_presence_of(:email) } it { should allow_value("f@b.com").for(:email) } it { should_not allow_value("test").for(:email) } end
  • 47. let() gotcha describe User, ".admin_names" do let(:admin) { User.create!(:admin => true, :first => "Clark", :last => "Kent")} let(:avg_joe) { User.create!(:admin => false, :first => "Joe", :last => "Shmo")} subject { admin_names } it { should include "Clark Kent" } it { should_not include "Joe Shmo" } end spec/user_spec.rb
  • 48. let() work-around describe User, ".admin_names" do let(:admin) { User.create!(:admin => true, :first => "Clark", :last => "Kent")} let(:avg_joe) { User.create!(:admin => false, :first => "Joe", :last => "Shmo")} subject { User.admin_names } before { admin && avg_joe } it { should include "Clark Kent" } it { should_not include "Joe Shmo" } end spec/user_spec.rb
  • 49. let!() describe User, ".admin_names" do let!(:admin) { User.create!(:admin => true, :first => "Clark", :last => "Kent")} let!(:avg_joe) { User.create!(:admin => false, :first => "Joe", :last => "Shmo")} subject { User.admin_names } it { should include "Clark Kent" } it { should_not include "Joe Shmo" } end spec/user_spec.rb

Editor's Notes

  1. \n
  2. going beyond the basics\noffering some opinions\nhighlighting some (relatively) new hotness\n
  3. \n
  4. \n
  5. partial simple project directory structure\n
  6. Keep spec_helper slim.\n\nInclude it in all spec files.\n\nEspecially in a Rails project. You’ll want to regenerate it when you update RSpec.\n\nMove Helpers into spec/support/. I even move configuration there (configure.rb).\n
  7. Command line options that can be specified in .rspec when using the RSpec Rake task.\n
  8. Output format\n
  9. Line number of a context/describe block or example\n
  10. tags\n
  11. An exercise in refactoring some specs\n
  12. Original spec\n
  13. This example uses the RSpec matcher DSL.\n\nMatchers can be created from scratch as well. To do so you need:\nA module with a method (e.g. have_attribute()) that instantiates a class\nThe class must define matches?(target), description(), failure_message_for_should(), failure_message_for_should_not()\n
  14. Using our new custom matcher, have_attribute()\n
  15. \n
  16. implicit subject()\n\ncall “should” off “nothing”\n
  17. Without redundant example (it) messages\n
  18. Derived subject().\n\nUse Class, not String as argument to describe()\n
  19. \n
  20. If AttributeMatchers are included in Spec::Runner configuration, we don’t need to include it here\n
  21. Original spec\n
  22. Hmmm... Looks similar to martini_spec\n
  23. Now both Whiskey and Martini have booze and glass attributes.\n\nLots of overlap.\n
  24. Note that there are NO INSTANCE VARIABLES!\n\nWe use the subject() here.\n
  25. The shared examples with use the derived subject().\n
  26. \n
  27. \n
  28. Also note the “include” matcher!\n
  29. There is a gotcha! More if we have time.\n
  30. \n
  31. OR\n\nlose the context() and break the example into its own describe() block\n\nNote the use of the “.” before the class method name (“new”). This is a common convention. “#” is used for instance methods\n
  32. “items” is just sugar, we could use whatever word we want here e.g. “elements”\n
  33. OR\n\na more readable example\n
  34. I would not advocate this usage of expect().\nOther uses:\nexpect{}.to change{}.by(1)\nexpect{}.to raise_error\n\n
  35. Any call to the .new() method on the Printer class will return epson.\n\nNote that epson is a test double(). It’s dumb. It doesn’t know how to do (or respond to) the real Printer methods.\n
  36. Other test double libraries have test spies.\n
  37. Configuring RSpec\n
  38. Helpers included in RSpec configuration are included for all specs if no :type is specified.\n
  39. BEWARE before(:all)!!! Not just in RSpec.configure, but in all specs.\n \n Who’s been burned by before(:all)?\n \n Improper use can lead to the unit test anti-pattern called “Interacting Tests” (or “Generous Leftovers”) and therefor erratic and hard to resolve failures.\n
  40. Every example and example group comes with metadata information\n\nWhen you run the $ rspec command, only the examples that have :focus => true tag in the hash.\n\nIf there are no examples tagged with “:focus => true”, all examples will be run. \n
  41. Do NOT run examples that are tagged with a different Ruby version when running the “rspec” command.\n
  42. \n
  43. Integrated fixture loading (and unloading).\nSpecial generators that generate RSpec code examples.\nHelp isolate your classes using example groups (e.g. Controller Examples don’t actually render Views)\nRails specific Matchers.\n
  44. To name a few Matchers.\n
  45. \n
  46. Shoulda’s ActiveRecord Matchers.\n
  47. \n
  48. THIS WILL FAIL!\n
  49. THIS WILL FAIL!\n
  50. Green\n
  51. Implementation possibility\n
  52. Distributed (across cores, processors and even other machines) testing framework\n
  53. A DRb test server implementation that forks itself every time your tests are run instead of unloading the RAILS constant.\n
  54. Rspec::Matchers now offers you two approaches to differentiating between object identity.\n