testing with rspec (rubyday 2011)
DESCRIPTION
The slides of my "Testing with RSpec" talk at RubyDay 2011.TRANSCRIPT
![Page 2: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/2.jpg)
Me.about(:robodomain)
Monday, June 20, 2011
![Page 3: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/3.jpg)
Me.about(:ifad)
Monday, June 20, 2011
![Page 4: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/4.jpg)
describe RSpec, "Agenda"
Monday, June 20, 2011
![Page 5: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/5.jpg)
Monday, June 20, 2011
![Page 6: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/6.jpg)
Monday, June 20, 2011
![Page 7: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/7.jpg)
Testing
Monday, June 20, 2011
![Page 8: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/8.jpg)
TDD seems to be applicable in various domains and can
significantly reduce the defect density of developed
software without significant productivity reduction of the
development team.
http://www.infoq.com/news/2009/03/TDD-Improves-
Quality
Monday, June 20, 2011
![Page 9: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/9.jpg)
The pre-release defect density of the four products,
measured as defects per thousand lines of code,
decreased between 40% and 90% relative to the
projects that did not use TDD. The teams' management
reported subjectively a 15–35% increase in initial
development time for the teams using TDD, though the
teams agreed that this was offset by reduced
maintenance costs.
Monday, June 20, 2011
![Page 10: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/10.jpg)
Monday, June 20, 2011
![Page 11: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/11.jpg)
$ rspec
http://relishapp.com/rspec
https://github.com/rspec
Monday, June 20, 2011
![Page 12: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/12.jpg)
Monday, June 20, 2011
![Page 13: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/13.jpg)
describe RSpec, "Features"
Monday, June 20, 2011
![Page 14: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/14.jpg)
Readabilitydescribe Whois::Client do describe "#initialize" do it "accepts a timeout setting with a value in seconds" do klass.new(:timeout => 100).timeout.should == 100 end
it "accepts a timeout setting with a nil value" do klass.new(:timeout => nil).timeout.should be_nil end end
describe "#query" do it "detects email" do expect { klass.new.query("[email protected]") }.to raise_error(Whois::ServerNotSupported) end endend
Monday, June 20, 2011
![Page 15: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/15.jpg)
Readabilitydescribe Whois::Client do describe "#initialize" do it "accepts a timeout setting with a value in seconds" do klass.new(:timeout => 100).timeout.should == 100 end
it "accepts a timeout setting with a nil value" do klass.new(:timeout => nil).timeout.should be_nil end end
describe "#query" do it "detects email" do expect { klass.new.query("[email protected]") }.to raise_error(Whois::ServerNotSupported) end endend
Monday, June 20, 2011
![Page 16: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/16.jpg)
Isolationdescribe UsersController do context "when logged as administrator" do before(:each) do log_in_as @admin = Factory(:user, :username => "admin") end
context "with a bunch of users" do before(:each) { @users = 3.times.map { Factory(:user) } }
describe "GET index" end
context "with no users" do describe "GET new" describe "POST create" end
describe "with a user" do before(:each) { @user = Factory(:user) }
describe "GET show" end endend
Monday, June 20, 2011
![Page 17: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/17.jpg)
Extensibledescribe 9 do it "should be a multiple of 3" do (9 % 3).should == 0 endend
# vs
RSpec::Matchers.define :be_a_multiple_of do |expected| match do |actual| actual % expected == 0 endend
describe 9 do it "should be a multiple of 3" do 9.should be_a_multiple_of(3) endend
Monday, June 20, 2011
![Page 18: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/18.jpg)
describe RSpec, "Syntax"
Monday, June 20, 2011
![Page 19: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/19.jpg)
Basic Exampledescribe String do describe "#upcase" do it "returns the original string converted to uppercase" do "hello".upcase.should == "HELLO" end
it "returns a String" do "hello".upcase.should be_a(String) end
it "does not change the original string" do string = "hello" string.upcase string.should_not == "HELLO" end endend
Monday, June 20, 2011
![Page 20: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/20.jpg)
Basic Exampledescribe String do describe "#upcase" do it "returns the original string converted to uppercase" do "hello".upcase.should == "HELLO" end
it "returns a String" do "hello".upcase.should be_a(String) end
it "does not change the original string" do string = "hello" string.upcase string.should_not == "HELLO" end endend
Monday, June 20, 2011
![Page 21: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/21.jpg)
context / describedescribe "something" do context "in one context" do it "does one thing" do end end
context "in another context" do it "does another thing" do end endend
Monday, June 20, 2011
![Page 22: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/22.jpg)
before / afterdescribe "before / after" do before(:each) {} before(:all) {} before(:suite) {}
after(:each) {} after(:all) {} after(:suite) {}end
# Before and after blocks are called in the following order:# # before suite# before all# before each# after each# after all# after suite
Monday, June 20, 2011
![Page 23: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/23.jpg)
before / afterdescribe "before / after" do before(:each) do @hash = {} end
it "does something" do @hash[:key] = "value" @hash[:key].should_not be_empty endend
Monday, June 20, 2011
![Page 24: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/24.jpg)
let$count = 0describe "let" do let(:count) { $count += 1 }
it "memoizes the value" do count.should == 1 count.should == 1 end
it "is not cached across examples" do count.should == 2 endend
Monday, June 20, 2011
![Page 25: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/25.jpg)
Implicit subjectdescribe Array do describe "when first created" do it "should be empty" do subject.should eq([]) end endend
Monday, June 20, 2011
![Page 26: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/26.jpg)
subjectdescribe Array do subject { [1,2,3] }
describe "with some elements" do it "should have the prescribed elements" do subject.should == [1,2,3] end endend
Monday, June 20, 2011
![Page 27: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/27.jpg)
expectdescribe Integer do describe "#/" do it "raises ZeroDivisionError when divisor is 0" do lambda do 1 / 0 end.should raise_error(ZeroDivisionError) end endend
# vs
describe Integer do describe "#/" do it "raises ZeroDivisionError when divisor is 0" do expect { 1 / 0 }.to raise_error(ZeroDivisionError) end endend
Monday, June 20, 2011
![Page 28: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/28.jpg)
Shared Behaviorsshared_examples "a collection" do let(:collection) { described_class.new([7, 2, 4]) }
context "initialized with 3 items" do it "says it has three items" do collection.size.should eq(3) end end
describe "#include?" do context "with an an item that is in the collection" do it "returns true" do collection.include?(7).should be_true end end
context "with an an item that is not in the collection" do it "returns false" do collection.include?(9).should be_false end end endend
Monday, June 20, 2011
![Page 29: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/29.jpg)
Shared Behaviorsdescribe Array do it_behaves_like "a collection"end
describe Set do it_behaves_like "a collection"end
Monday, June 20, 2011
![Page 30: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/30.jpg)
pendingdescribe Hash do it "adds a key" do { :key => "value" }[:key].should == "value" end
it "does something unknown"
it "does something buggy" do pending "This method is buggy" endend
describe Integer do before(:each) { pending }
it "computes 1 + 1" do (1 + 1).should == 2 end
it "computes 1 - 1" do (1 - 1).should == 0 endend
Monday, June 20, 2011
![Page 31: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/31.jpg)
pendingdescribe Hash do it "adds a key" do { :key => "value" }[:key].should == "value" end
it "does something unknown"
it "does something buggy" do pending "This method is buggy" endend
describe Integer do before(:each) { pending }
it "computes 1 + 1" do (1 + 1).should == 2 end
it "computes 1 - 1" do (1 - 1).should == 0 endend
Monday, June 20, 2011
![Page 32: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/32.jpg)
pendingdescribe "an example" do xit "is pending using xit" do true.should be(true) endend
describe "an example" do it "checks something" do (3+4).should == 7 end pending do "string".reverse.should == "gnirts" endend
Monday, June 20, 2011
![Page 33: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/33.jpg)
Metadatadescribe "something", :this => { :is => :arbitrary } do it "does something", :and => "so is this" do # ... endend
RSpec.configure do |c| c.filter_run_excluding :ruby => lambda {|version| !(RUBY_VERSION.to_s =~ /^#{version.to_s}/) }end describe "something" do it "does something", :ruby => 1.8 do # .... end it "does something", :ruby => 1.9 do # .... endend
Monday, June 20, 2011
![Page 34: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/34.jpg)
MetadataRSpec.configure do |c| c.filter_run :focus => trueend
describe "something", :focus => true do it "does something" do # .... endend
RSpec.configure do |c| c.filter_run_excluding :slow => trueend
describe "something", :slow => true do it "does something" do # .... endend
Monday, June 20, 2011
![Page 35: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/35.jpg)
describe RSpec, "Integration"
Monday, June 20, 2011
![Page 36: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/36.jpg)
RSpec
Monday, June 20, 2011
![Page 37: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/37.jpg)
describe AccountsController do describe "GET show" do before(:each) do get :show end
it { should respond_with :success } it { should render_template "accounts/show" }
it "assigns user" do assigns(:user).should == @user end endend
RSpec# Gemfilegroup :development, :test do gem 'rspec-rails', '~> 2.6.0'end
spec folder
Monday, June 20, 2011
![Page 38: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/38.jpg)
RSpecRSpec.configure do |config| config.include Rack::Test::Methodsend
describe Tremonti::Application do def app Tremonti::Application end
describe "/" do it "should respond with 200" do get "/" last_response.should be_ok last_response.body.should == "Hello from RoboFinance!" end endend
rack-test
Monday, June 20, 2011
![Page 39: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/39.jpg)
RSpec MochaRR
RSpec.configure do |config|
# == Mock Framework # # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line: # config.mock_with :mocha # config.mock_with :flexmock # config.mock_with :rr
end
Monday, June 20, 2011
![Page 40: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/40.jpg)
RSpec Factoriesdescribe BillingCharge do subject { Factory.build(:billing_charge) }
describe "associations" do it { should belong_to(:user) } end
describe "validations" do it "is valid with factory" do Factory.build(:billing_charge).should be_valid end
it { should validate_presence_of(:user_id) }
it { should validate_format_of(:period).with('2010-02') } it { should validate_format_of(:period).not_with('201002') } it { should validate_format_of(:period).not_with('2010') } endend
Monday, June 20, 2011
![Page 41: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/41.jpg)
describe RSpec, "Best Practices"
Monday, June 20, 2011
![Page 42: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/42.jpg)
describe vs contextdescribe ".guess" do it "recognizes tld" do s = Whois::Server.guess(".com") s.should be_a(Whois::Server::Adapters::Base) s.type.should == :tld end
context "when the input is a tld" do it "returns a IANA adapter" do Whois::Server.guess(".com").should == Whois::Server.factory(:tld, ".", "whois.iana.org") end end
context "when the input is a domain" do it "lookups definitions and returns the adapter" do Whois::Server.guess("example.test").should == Whois::Server.factory(:tld, ".test", "whois.test") end endend
Monday, June 20, 2011
![Page 43: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/43.jpg)
it vs specifydescribe User do before do @user = User.new :username => 'weppos' end
it "is not an administrator" do @user.should_not be_admin endend
# vs.
describe User do let(:user) do User.new :username => 'weppos' end
specify do user.should_not be_admin endend
Monday, June 20, 2011
![Page 44: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/44.jpg)
shoulddescribe "#order_price" do it "should be a Money" do # ... end
it "should return nil when amount is blank" do # ... endend
# vs
describe "#order_price" do it "is a Money" do # ... end
it "returns nil when amount is blank" do # ... endend
Monday, June 20, 2011
![Page 45: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/45.jpg)
context vs itdescribe Hash, "#size" do it "returns 0 when the Hash is empty" do end
it "returns the number of elements when the Hash is not empty" do endend
# vs
describe Hash, "#size" do context "when the Hash is empty" do it "returns 0" do end end
context "when the Hash is not empty" do it "returns the number of elements" do end endend
Monday, June 20, 2011
![Page 46: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/46.jpg)
Instance vs Class methodsdescribe Time do describe ".parse" do it "converts given string into a Time" do Time.parse('2010-06-12').should == Time.mktime(2010, 06, 12) end end
describe "#to_i" do it "returns the timestamp corresponding to the Time object" do t = Time.mktime(2010, 06, 12) t.to_i.should == 1276293600 end endend
Monday, June 20, 2011
![Page 47: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/47.jpg)
spec_helper.rb & /support
Monday, June 20, 2011
![Page 48: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/48.jpg)
Demo Time
Monday, June 20, 2011
![Page 49: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/49.jpg)
Choose the right tool...
Monday, June 20, 2011
![Page 50: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/50.jpg)
... and Test!
Monday, June 20, 2011
![Page 51: Testing with RSpec (RubyDay 2011)](https://reader033.vdocuments.net/reader033/viewer/2022052321/554a03a5b4c905e56c8b5384/html5/thumbnails/51.jpg)
Thanks!
Monday, June 20, 2011