Testing with RSpec (RubyDay 2011)
Post on 06-May-2015
2807 Views
Preview:
DESCRIPTION
Transcript
Simone Carlettisimone@carletti.name
twitter: @weppos
Testing with RSpec
2011
Monday, June 20, 2011
Me.about(:robodomain)
Monday, June 20, 2011
Me.about(:ifad)
Monday, June 20, 2011
describe RSpec, "Agenda"
Monday, June 20, 2011
Monday, June 20, 2011
Monday, June 20, 2011
Testing
Monday, June 20, 2011
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
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
Monday, June 20, 2011
$ rspec
http://relishapp.com/rspec
https://github.com/rspec
Monday, June 20, 2011
Monday, June 20, 2011
describe RSpec, "Features"
Monday, June 20, 2011
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("weppos@weppos.net") }.to raise_error(Whois::ServerNotSupported) end endend
Monday, June 20, 2011
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("weppos@weppos.net") }.to raise_error(Whois::ServerNotSupported) end endend
Monday, June 20, 2011
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
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
describe RSpec, "Syntax"
Monday, June 20, 2011
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
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
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
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
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
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
Implicit subjectdescribe Array do describe "when first created" do it "should be empty" do subject.should eq([]) end endend
Monday, June 20, 2011
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
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
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
Shared Behaviorsdescribe Array do it_behaves_like "a collection"end
describe Set do it_behaves_like "a collection"end
Monday, June 20, 2011
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
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
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
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
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
describe RSpec, "Integration"
Monday, June 20, 2011
RSpec
Monday, June 20, 2011
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
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
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
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
describe RSpec, "Best Practices"
Monday, June 20, 2011
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
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
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
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
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
spec_helper.rb & /support
Monday, June 20, 2011
Demo Time
Monday, June 20, 2011
Choose the right tool...
Monday, June 20, 2011
... and Test!
Monday, June 20, 2011
Thanks!
Monday, June 20, 2011
top related