SlideShare a Scribd company logo
1 of 46
RSpec & Rails
Bunlong Van – Rubyist/Rails Developer
Mail: bunlong.van@gmail.com
Blog: http://geekhmer.github.io
Cover
- What is Rspec?
- RSpec features
- RSpec in action
- Stubs & Mocks
- Stubs & Mocks using RSpec
What is RSpec ?
- Testing framework for Ruby on Rails.
- Replacement for RoR built-in testing tool.
TestUnit
class Calculator < Test::Unit::TestCase
def test_addition
assert_equal(8, Calculator.new(6, 2).addition)
end
def test_subtraction
assert_same(4, Calculator.new(6, 2).subtraction)
end
end
RSpec
desribe Calculator do
let(:calculator) { Calculator.new(6,2) }
it "should return 8 when adding 6 and 2" do
calculator.addition.should eql(8)
end
it "should return 4 when subtracting 2 from 6" do
calculator.subtraction.should eql(4)
end
end
RSpec basics
describe MyClass do # creates initial scope
before do
@object = MyClass.new
end
describe "#some_method" do # creates new scope
it "should ..." do
@object.should ...
end
context "when authorized" do # creates new scope
before do
@object.authorized = true
end
RSpec basics (Con.)
it "should ..." do
@object.should ...
end
end
context "when not authorized" do # creates new scope
it "should ..." do
@object.should ...
end
end
end
it "should ..." do
pending "Fix some model first" # creates pending test
end
end
Why RSpec?
- Readability
- Tests documentation and failure messages
Readability
describe Campaign do
it "should be visible by default" do
campaign.should be_visible
end
it "should have performances visible by default" do
campaign.performances_visible.should be_true
end
it "should not be published at start" do
campaign.should_not be_published
end
Readability (Con.)
it "should not be ready to publish at start - without performances, etc" do
campaign.should_not be_ready_to_publish
end
describe "#allowed_performance_kinds" do
it "should allow all by default" do
campaign.allowed_performance_kinds.should == Performance.kinds
end
end
end
Tests documentation and failure
messages
When tests output matter
- Built-in profiler
- Test run filters
- Conventions
- Built-in matchers
Built-in profiler
Test run filters
def old_ruby
RUBY_VERSION != "1.9.2"
end
describe TrueClass do
it "should be true for true", :if => old_ruby do
true.should be_true
end
it "should be true for String", :current => true do
"".should be_true
end
Test run filters (Cons.)
it "should be true for Fixnum" do
0.should be_true
end
end
Conventions
Built-in matchers
target.should satisfy {|arg| ...}
target.should_not satisfy {|arg| ...}
target.should equal <value>
target.should not_equal <value>
target.should be_close <value>, <tolerance>
target.should_not be_close <value>, <tolerance>
target.should be <value>
target.should_not be <value>
target.should predicate [optional args]
target.should be_predicate [optional args]
target.should_not predicate [optional args]
target.should_not be_predicate [optional args]
target.should be < 6
target.should be_between(1, 10)
Built-in matchers (Cons.)
target.should match <regex>
target.should_not match <regex>
target.should be_an_instance_of <class>
target.should_not be_an_instance_of <class>
target.should be_a_kind_of <class>
target.should_not be_a_kind_of <class>
target.should respond_to <symbol>
target.should_not respond_to <symbol>
lambda {a_call}.should raise_error
lambda {a_call}.should raise_error(<exception> [, message])
lambda {a_call}.should_not raise_error
lambda {a_call}.should_not raise_error(<exception> [, message])
Built-in matchers (Cons.)
proc.should throw <symbol>
proc.should_not throw <symbol>
target.should include <object>
target.should_not include <object>
target.should have(<number>).things
target.should have_at_least(<number>).things
target.should have_at_most(<number>).things
target.should have(<number>).errors_on(:field)
expect { thing.approve! }.to change(thing, :status)
.from(Status::AWAITING_APPROVAL)
.to(Status::APPROVED)
expect { thing.destroy }.to change(Thing, :count).by(-1)
Problems ?
- Hard to learn at the beginning
- Routing tests could have more detailed failure messages
- Rails upgrade can break tests compatibility
RSpec in action
- Model specs (placed under spec/models director)
- Controller specs (placed under spec/controllers directory)
- Helper specs (placed under spec/helpers directory)
- View specs (placed under spec/views directory)
- Routing specs (placed under spec/routing directory)
Model specs
describe Campaign do
it "should be visible by default" do
campaign.should be_visible
end
it "should have performances visible by default" do
campaign.performances_visible.should be_true
end
it "should not be published at start" do
campaign.should_not be_published
end
Model specs (Cons.)
it "should not be ready to publish at start - without performances, etc" do
campaign.should_not be_ready_to_publish
end
describe "#allowed_performance_kinds" do
it "should allow all by default" do
campaign.allowed_performance_kinds.should == Performance.kinds
end
end
end
Controller specs
describe SessionsController do
render_views
describe "CREATE" do
context "for virtual user" do
before do
stub_find_user(virtual_user)
end
it "should not log into peoplejar" do
post :create, :user => {:email => virtual_user.email,
:password => virtual_user.password }
response.should_not redirect_to(myjar_dashboard_path)
end
end
Controller specs (Cons.)
context "for regular user" do
before do
stub_find_user(active_user)
end
it "should redirect to myjar when login data is correct" do
post :create, :user => {:email => active_user.email,
:password => active_user.password }
response.should redirect_to(myjar_dashboard_path)
end
end
end
end
Helper specs
describe CampaignsHelper do
let(:campaign) { Factory.stub(:campaign) }
let(:file_name) { "meldung.jpg" }
it "should return the same attachment URL as paperclip
if there is no attachment" do
campaign.stub(:featured_image_file_name).and_return(nil)
helper.campaign_attachment_url(campaign, :featured_image).
should eql(campaign.featured_image.url)
end
it "should return the same attachment URL as paperclip if there
is attachment" do
campaign.stub(:featured_image_file_name).and_return(file_name)
Helper specs (Cons.)
helper.campaign_attachment_url(campaign, :featured_image).
should eql(campaign.featured_image.url)
end
end
View specs
# view at views/campaigns/index.html.erb
<%= content_for :actions do %>
<div id="hb_actions" class="browse_arena">
<div id="middle_actions">
<ul class="btn">
<li class="btn_blue"><%= create_performance_link %></li>
</ul>
</div>
</div>
<% end %>
<div id="interest_board_holder">
<%= campaings_wall_template(@campaigns) %>
</div>
View specs (Cons.)
# spec at spec/views/campaigns/index.html.erb_spec.rb
describe "campaigns/index.html.erb" do
let(:campaign) { Factory.stub(:campaign) }
it "displays pagination when there are more than 20 published
campaigns" do
assign(:campaigns, (1..21).map { campaign }.
paginate(:per_page => 2) )
render
rendered.should include("Prev")
rendered.should include("Next")
end
end
Routing specs
describe "home routing", :type => :controller do
it "should route / to Home#index" do
{ :get => "/" }.should route_to(:controller => "home", :action => "index",
:subdomain => false)
end
it "should route / with subdomain to Performances::Performances#index
do
{ :get => "http://kzkgop.test.peoplejar.net" }.
should route_to(:namespace => nil, :controller =>
"performances/performances", :action => "index")
end
end
Routing specs (Cons.)
describe "error routing", :type => :controller do
it "should route not existing route Errors#new" do
{ :get => "/not_existing_route" }.should route_to(:controller => "errors",
:action => "new", :path => "not_existing_route")
end
End
describe "icebreaks routing" do
it "should route /myjar/icebreaks/initiated to
Icebreaks::InitiatedIcebreaks#index" do
{ :get => "/myjar/icebreaks/initiated" }.should
route_to(:controller => "icebreaks/initiated_icebreaks",
:action => "index")
end
end
Routing specs (Cons.)
describe "admin routing" do
it "should route /admin to Admin::Base#index" do
{ :get => "/admin" }.should route_to(:controller => "admin/welcome",
:action => "index")
end
end
Stubs & Mocks
Back to unit test assumptions
- A unit is the smallest testable part of an application
- The goal of unit testing is to isolate each part of the program and show
that the individual parts are correct
- Ideally, each test case is independent from the others
you.should use_stubs!
- Isolate your unit tests from external libraries and dependencies
- Propagate skinny methods which has low responsibility
- Single bug should make only related tests fail
- Speed up tests
PeopleJar is using
Are there any problems ?
- Writing test is more time consuming
- Need to know stubbed library internal implementations
- Need to write an integration test first
Stubs in action
User.stub(:new) # => nil
User.stub(:new).and_return(true)
user_object = User.new
user_object.stub(:save).and_return(true)
User.stub(:new).and_return(user_object)
user_object.stub(:update_attributes).with(:username => "test").
and_return(true)
User.stub(:new).and_return(user_object)
User.any_instance.stub(:save).and_return(true)
# User.active.paginate
User.stub_chain(:active, :paginate).and_return([user_object])
Stubs in action
User.stub(:new) # => nil
User.stub(:new).and_return(true)
user_object = User.new
user_object.stub(:save).and_return(true)
User.stub(:new).and_return(user_object)
user_object.stub(:update_attributes).with(:username => "test").
and_return(true)
User.stub(:new).and_return(user_object)
User.any_instance.stub(:save).and_return(true)
# User.active.paginate
User.stub_chain(:active, :paginate).and_return([user_object])
Stubs in action (Cons.)
user_object.stub(:set_permissions).with(an_instance_of(String),
anything).and_return(true)
user_object.unstub(:set_permissions)
# user_object.set_permissions("admin", true) # => true (will use stubbed
method)
# user_object.set_permissions("admin") # => false (will call real method)
Mocks in action
User.should_receive(:new) # => nil
User.should_receive(:new).and_return(true)
User.should_not_receive(:new)
user_object = User.new
user_object.should_receive(:save).and_return(true)
User.stub(:new).and_return(user_object)
user_object.should_receive(:update_attributes).
with(:username => "test").and_return(true)
User.stub(:new).and_return(user_object)
User.any_instance.should_receive(:save).and_return(true) # !
Mocks in action (Cons.)
user_object.should_receive(:update_attributes).once # default
user_object.should_receive(:update_attributes).twice
user_object.should_receive(:update_attributes).exactly(3).times
user_object.should_receive(:set_permissions).
with(an_instance_of(String), anything)
# user_object.set_permissions("admin", true) # Success
# user_object.set_permissions("admin") # Fail
What's the difference between
Stubs and Mocks
- Mocks are used to define expectations and verify them
- Stubs allows for defining eligible behavior
- Stubs will not cause a test to fail due to unfulfilled expectation
In practice - Stub failure
describe ".to_csv_file" do
it "should generate CSV output" do
User.stub(:active).and_return([user])
User.to_csv_file.should == "#{user.display_name},#{user.email}n"
end
end
In practice - Mock failure
describe "#facebook_uid=" do
it "should build facebook setting instance if not exists when setting uid"
do
user.should_receive(:build_facebook_setting).with(:uid => "123")
user.facebook_uid = "123"
end
end
Question?

More Related Content

What's hot

RSpec and Rails
RSpec and RailsRSpec and Rails
RSpec and RailsAlan Hecht
 
Introduction to testing in Rails
Introduction to testing in RailsIntroduction to testing in Rails
Introduction to testing in Railsbenlcollins
 
Testing Javascript with Jasmine
Testing Javascript with JasmineTesting Javascript with Jasmine
Testing Javascript with JasmineTim Tyrrell
 
How To Test Everything
How To Test EverythingHow To Test Everything
How To Test Everythingnoelrap
 
Testing JS with Jasmine
Testing JS with JasmineTesting JS with Jasmine
Testing JS with JasmineEvgeny Gurin
 
Introduction to unit testing
Introduction to unit testingIntroduction to unit testing
Introduction to unit testingArtem Shoobovych
 
AngularJS Unit Testing
AngularJS Unit TestingAngularJS Unit Testing
AngularJS Unit TestingPrince Norin
 
Painless Javascript Unit Testing
Painless Javascript Unit TestingPainless Javascript Unit Testing
Painless Javascript Unit TestingBenjamin Wilson
 
Why you should be using the shiny new C# 6.0 features now!
Why you should be using the shiny new C# 6.0 features now!Why you should be using the shiny new C# 6.0 features now!
Why you should be using the shiny new C# 6.0 features now!Eric Phan
 
2019-08-23 API contract testing with Dredd
2019-08-23 API contract testing with Dredd2019-08-23 API contract testing with Dredd
2019-08-23 API contract testing with DreddRyan M Harrison
 
Inversion Of Control
Inversion Of ControlInversion Of Control
Inversion Of ControlChad Hietala
 
Crossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end FrameworkCrossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end FrameworkDaniel Spector
 
Introduction to Python decorators
Introduction to Python decoratorsIntroduction to Python decorators
Introduction to Python decoratorsrikbyte
 

What's hot (20)

Rspec 101
Rspec 101Rspec 101
Rspec 101
 
RSpec and Rails
RSpec and RailsRSpec and Rails
RSpec and Rails
 
Introduction to testing in Rails
Introduction to testing in RailsIntroduction to testing in Rails
Introduction to testing in Rails
 
TDD, BDD, RSpec
TDD, BDD, RSpecTDD, BDD, RSpec
TDD, BDD, RSpec
 
Testing Javascript with Jasmine
Testing Javascript with JasmineTesting Javascript with Jasmine
Testing Javascript with Jasmine
 
Clean Code
Clean CodeClean Code
Clean Code
 
RSpec
RSpecRSpec
RSpec
 
Rails is not just Ruby
Rails is not just RubyRails is not just Ruby
Rails is not just Ruby
 
Excellent
ExcellentExcellent
Excellent
 
How To Test Everything
How To Test EverythingHow To Test Everything
How To Test Everything
 
Testing JS with Jasmine
Testing JS with JasmineTesting JS with Jasmine
Testing JS with Jasmine
 
Introduction to unit testing
Introduction to unit testingIntroduction to unit testing
Introduction to unit testing
 
TDD with PhpSpec
TDD with PhpSpecTDD with PhpSpec
TDD with PhpSpec
 
AngularJS Unit Testing
AngularJS Unit TestingAngularJS Unit Testing
AngularJS Unit Testing
 
Painless Javascript Unit Testing
Painless Javascript Unit TestingPainless Javascript Unit Testing
Painless Javascript Unit Testing
 
Why you should be using the shiny new C# 6.0 features now!
Why you should be using the shiny new C# 6.0 features now!Why you should be using the shiny new C# 6.0 features now!
Why you should be using the shiny new C# 6.0 features now!
 
2019-08-23 API contract testing with Dredd
2019-08-23 API contract testing with Dredd2019-08-23 API contract testing with Dredd
2019-08-23 API contract testing with Dredd
 
Inversion Of Control
Inversion Of ControlInversion Of Control
Inversion Of Control
 
Crossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end FrameworkCrossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end Framework
 
Introduction to Python decorators
Introduction to Python decoratorsIntroduction to Python decorators
Introduction to Python decorators
 

Viewers also liked

Автоматизируем тестирование UI с Ruby, Cucumber и Selenium
Автоматизируем тестирование UI с Ruby, Cucumber и Selenium Автоматизируем тестирование UI с Ruby, Cucumber и Selenium
Автоматизируем тестирование UI с Ruby, Cucumber и Selenium SQALab
 
Railsで春から始めるtdd生活
Railsで春から始めるtdd生活Railsで春から始めるtdd生活
Railsで春から始めるtdd生活Yamamoto Kazuhisa
 
Системное тестирование приложений на Ruby on Rails с применением Rspec и Cap...
Системное тестирование  приложений на Ruby on Rails с применением Rspec и Cap...Системное тестирование  приложений на Ruby on Rails с применением Rspec и Cap...
Системное тестирование приложений на Ruby on Rails с применением Rspec и Cap...lshevtsov
 
Swift distributed tracing method and tools v2
Swift distributed tracing method and tools v2Swift distributed tracing method and tools v2
Swift distributed tracing method and tools v2zhang hua
 
Action Controller Overview, Season 1
Action Controller Overview, Season 1Action Controller Overview, Season 1
Action Controller Overview, Season 1RORLAB
 
Control review for iOS
Control review for iOSControl review for iOS
Control review for iOSWilliam Price
 
Let's Learn Ruby - Basic
Let's Learn Ruby - BasicLet's Learn Ruby - Basic
Let's Learn Ruby - BasicEddie Kao
 
jQuery For Beginners - jQuery Conference 2009
jQuery For Beginners - jQuery Conference 2009jQuery For Beginners - jQuery Conference 2009
jQuery For Beginners - jQuery Conference 2009Ralph Whitbeck
 
BDD style Unit Testing
BDD style Unit TestingBDD style Unit Testing
BDD style Unit TestingWen-Tien Chang
 
Ruby On Rails: Web-разработка по-другому!
Ruby On Rails: Web-разработка по-другому!Ruby On Rails: Web-разработка по-другому!
Ruby On Rails: Web-разработка по-другому!Constantin Kichinsky
 
Learning jQuery in 30 minutes
Learning jQuery in 30 minutesLearning jQuery in 30 minutes
Learning jQuery in 30 minutesSimon Willison
 
A swift introduction to Swift
A swift introduction to SwiftA swift introduction to Swift
A swift introduction to SwiftGiordano Scalzo
 
Introduction to html
Introduction to htmlIntroduction to html
Introduction to htmlvikasgaur31
 
Infinum iOS Talks #1 - Swift under the hood: Method Dispatching by Vlaho Poluta
Infinum iOS Talks #1 - Swift under the hood: Method Dispatching by Vlaho PolutaInfinum iOS Talks #1 - Swift under the hood: Method Dispatching by Vlaho Poluta
Infinum iOS Talks #1 - Swift under the hood: Method Dispatching by Vlaho PolutaInfinum
 
Introduction to Web Architecture
Introduction to Web ArchitectureIntroduction to Web Architecture
Introduction to Web ArchitectureChamnap Chhorn
 
jQuery and Rails: Best Friends Forever
jQuery and Rails: Best Friends ForeverjQuery and Rails: Best Friends Forever
jQuery and Rails: Best Friends Foreverstephskardal
 
Swift Programming Language
Swift Programming LanguageSwift Programming Language
Swift Programming LanguageGiuseppe Arici
 

Viewers also liked (20)

Basic RSpec 2
Basic RSpec 2Basic RSpec 2
Basic RSpec 2
 
Автоматизируем тестирование UI с Ruby, Cucumber и Selenium
Автоматизируем тестирование UI с Ruby, Cucumber и Selenium Автоматизируем тестирование UI с Ruby, Cucumber и Selenium
Автоматизируем тестирование UI с Ruby, Cucumber и Selenium
 
Railsで春から始めるtdd生活
Railsで春から始めるtdd生活Railsで春から始めるtdd生活
Railsで春から始めるtdd生活
 
Системное тестирование приложений на Ruby on Rails с применением Rspec и Cap...
Системное тестирование  приложений на Ruby on Rails с применением Rspec и Cap...Системное тестирование  приложений на Ruby on Rails с применением Rspec и Cap...
Системное тестирование приложений на Ruby on Rails с применением Rspec и Cap...
 
Swift distributed tracing method and tools v2
Swift distributed tracing method and tools v2Swift distributed tracing method and tools v2
Swift distributed tracing method and tools v2
 
Action Controller Overview, Season 1
Action Controller Overview, Season 1Action Controller Overview, Season 1
Action Controller Overview, Season 1
 
Control review for iOS
Control review for iOSControl review for iOS
Control review for iOS
 
Let's Learn Ruby - Basic
Let's Learn Ruby - BasicLet's Learn Ruby - Basic
Let's Learn Ruby - Basic
 
September2011aftma
September2011aftmaSeptember2011aftma
September2011aftma
 
jQuery For Beginners - jQuery Conference 2009
jQuery For Beginners - jQuery Conference 2009jQuery For Beginners - jQuery Conference 2009
jQuery For Beginners - jQuery Conference 2009
 
BDD style Unit Testing
BDD style Unit TestingBDD style Unit Testing
BDD style Unit Testing
 
Ruby On Rails: Web-разработка по-другому!
Ruby On Rails: Web-разработка по-другому!Ruby On Rails: Web-разработка по-другому!
Ruby On Rails: Web-разработка по-другому!
 
Learning jQuery in 30 minutes
Learning jQuery in 30 minutesLearning jQuery in 30 minutes
Learning jQuery in 30 minutes
 
A swift introduction to Swift
A swift introduction to SwiftA swift introduction to Swift
A swift introduction to Swift
 
Web application architecture
Web application architectureWeb application architecture
Web application architecture
 
Introduction to html
Introduction to htmlIntroduction to html
Introduction to html
 
Infinum iOS Talks #1 - Swift under the hood: Method Dispatching by Vlaho Poluta
Infinum iOS Talks #1 - Swift under the hood: Method Dispatching by Vlaho PolutaInfinum iOS Talks #1 - Swift under the hood: Method Dispatching by Vlaho Poluta
Infinum iOS Talks #1 - Swift under the hood: Method Dispatching by Vlaho Poluta
 
Introduction to Web Architecture
Introduction to Web ArchitectureIntroduction to Web Architecture
Introduction to Web Architecture
 
jQuery and Rails: Best Friends Forever
jQuery and Rails: Best Friends ForeverjQuery and Rails: Best Friends Forever
jQuery and Rails: Best Friends Forever
 
Swift Programming Language
Swift Programming LanguageSwift Programming Language
Swift Programming Language
 

Similar to Ruby on Rails testing with Rspec

Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Railsrstankov
 
Tdd for BT E2E test community
Tdd for BT E2E test communityTdd for BT E2E test community
Tdd for BT E2E test communityKerry Buckley
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasminePaulo Ragonha
 
RSpec User Stories
RSpec User StoriesRSpec User Stories
RSpec User Storiesrahoulb
 
Testing C# and ASP.net using Ruby
Testing C# and ASP.net using RubyTesting C# and ASP.net using Ruby
Testing C# and ASP.net using RubyBen Hall
 
Rails-like JavaScript using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript using CoffeeScript, Backbone.js and JasmineRails-like JavaScript using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript using CoffeeScript, Backbone.js and JasmineRaimonds Simanovskis
 
Rails Antipatterns | Open Session with Chad Pytel
Rails Antipatterns | Open Session with Chad Pytel Rails Antipatterns | Open Session with Chad Pytel
Rails Antipatterns | Open Session with Chad Pytel Engine Yard
 
Антипаттерны модульного тестирования
Антипаттерны модульного тестированияАнтипаттерны модульного тестирования
Антипаттерны модульного тестированияMitinPavel
 
Angular.js Fundamentals
Angular.js FundamentalsAngular.js Fundamentals
Angular.js FundamentalsMark
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overviewYehuda Katz
 
Real life-coffeescript
Real life-coffeescriptReal life-coffeescript
Real life-coffeescriptDavid Furber
 
AngularJS vs. Ember.js vs. Backbone.js
AngularJS vs. Ember.js vs. Backbone.jsAngularJS vs. Ember.js vs. Backbone.js
AngularJS vs. Ember.js vs. Backbone.jsMark
 
Controller Testing: You're Doing It Wrong
Controller Testing: You're Doing It WrongController Testing: You're Doing It Wrong
Controller Testing: You're Doing It Wrongjohnnygroundwork
 
Reliable Javascript
Reliable Javascript Reliable Javascript
Reliable Javascript Glenn Stovall
 

Similar to Ruby on Rails testing with Rspec (20)

Well
WellWell
Well
 
Why ruby
Why rubyWhy ruby
Why ruby
 
Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Rails
 
Tdd for BT E2E test community
Tdd for BT E2E test communityTdd for BT E2E test community
Tdd for BT E2E test community
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
 
RSpec User Stories
RSpec User StoriesRSpec User Stories
RSpec User Stories
 
Ruby gems
Ruby gemsRuby gems
Ruby gems
 
Rspec
RspecRspec
Rspec
 
Testing C# and ASP.net using Ruby
Testing C# and ASP.net using RubyTesting C# and ASP.net using Ruby
Testing C# and ASP.net using Ruby
 
Rails-like JavaScript using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript using CoffeeScript, Backbone.js and JasmineRails-like JavaScript using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript using CoffeeScript, Backbone.js and Jasmine
 
Rails Antipatterns | Open Session with Chad Pytel
Rails Antipatterns | Open Session with Chad Pytel Rails Antipatterns | Open Session with Chad Pytel
Rails Antipatterns | Open Session with Chad Pytel
 
Антипаттерны модульного тестирования
Антипаттерны модульного тестированияАнтипаттерны модульного тестирования
Антипаттерны модульного тестирования
 
Angular.js Fundamentals
Angular.js FundamentalsAngular.js Fundamentals
Angular.js Fundamentals
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overview
 
Real life-coffeescript
Real life-coffeescriptReal life-coffeescript
Real life-coffeescript
 
AngularJS vs. Ember.js vs. Backbone.js
AngularJS vs. Ember.js vs. Backbone.jsAngularJS vs. Ember.js vs. Backbone.js
AngularJS vs. Ember.js vs. Backbone.js
 
Controller Testing: You're Doing It Wrong
Controller Testing: You're Doing It WrongController Testing: You're Doing It Wrong
Controller Testing: You're Doing It Wrong
 
Reliable Javascript
Reliable Javascript Reliable Javascript
Reliable Javascript
 
Capistrano
CapistranoCapistrano
Capistrano
 
Controller specs
Controller specsController specs
Controller specs
 

More from Bunlong Van

scrummethodology-151002092252-lva1-app6891
scrummethodology-151002092252-lva1-app6891scrummethodology-151002092252-lva1-app6891
scrummethodology-151002092252-lva1-app6891Bunlong Van
 
Scrum methodology
Scrum methodologyScrum methodology
Scrum methodologyBunlong Van
 
Javascript dom event
Javascript dom eventJavascript dom event
Javascript dom eventBunlong Van
 
Javascript Object Oriented Programming
Javascript Object Oriented ProgrammingJavascript Object Oriented Programming
Javascript Object Oriented ProgrammingBunlong Van
 
Basic Javascript
Basic JavascriptBasic Javascript
Basic JavascriptBunlong Van
 
Real time web and mobile application with Erlang & Ruby programming language
Real time web and mobile application with Erlang & Ruby programming languageReal time web and mobile application with Erlang & Ruby programming language
Real time web and mobile application with Erlang & Ruby programming languageBunlong Van
 
How to develop app for facebook fan page
How to develop app for facebook fan pageHow to develop app for facebook fan page
How to develop app for facebook fan pageBunlong Van
 

More from Bunlong Van (9)

scrummethodology-151002092252-lva1-app6891
scrummethodology-151002092252-lva1-app6891scrummethodology-151002092252-lva1-app6891
scrummethodology-151002092252-lva1-app6891
 
Scrum methodology
Scrum methodologyScrum methodology
Scrum methodology
 
Javascript dom event
Javascript dom eventJavascript dom event
Javascript dom event
 
Javascript Object Oriented Programming
Javascript Object Oriented ProgrammingJavascript Object Oriented Programming
Javascript Object Oriented Programming
 
Basic Javascript
Basic JavascriptBasic Javascript
Basic Javascript
 
Real time web and mobile application with Erlang & Ruby programming language
Real time web and mobile application with Erlang & Ruby programming languageReal time web and mobile application with Erlang & Ruby programming language
Real time web and mobile application with Erlang & Ruby programming language
 
Why ruby?
Why ruby?Why ruby?
Why ruby?
 
How to develop app for facebook fan page
How to develop app for facebook fan pageHow to develop app for facebook fan page
How to develop app for facebook fan page
 
Why less?
Why less?Why less?
Why less?
 

Recently uploaded

Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplatePresentation.STUDIO
 
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...masabamasaba
 
Harnessing ChatGPT - Elevating Productivity in Today's Agile Environment
Harnessing ChatGPT  - Elevating Productivity in Today's Agile EnvironmentHarnessing ChatGPT  - Elevating Productivity in Today's Agile Environment
Harnessing ChatGPT - Elevating Productivity in Today's Agile EnvironmentVictorSzoltysek
 
%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Hararemasabamasaba
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Bert Jan Schrijver
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...SelfMade bd
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdfPearlKirahMaeRagusta1
 
tonesoftg
tonesoftgtonesoftg
tonesoftglanshi9
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastPapp Krisztián
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park masabamasaba
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...Shane Coughlan
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisamasabamasaba
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension AidPhilip Schwarz
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is insideshinachiaurasa2
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...masabamasaba
 

Recently uploaded (20)

Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
 
Harnessing ChatGPT - Elevating Productivity in Today's Agile Environment
Harnessing ChatGPT  - Elevating Productivity in Today's Agile EnvironmentHarnessing ChatGPT  - Elevating Productivity in Today's Agile Environment
Harnessing ChatGPT - Elevating Productivity in Today's Agile Environment
 
%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 
tonesoftg
tonesoftgtonesoftg
tonesoftg
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
 

Ruby on Rails testing with Rspec

  • 1. RSpec & Rails Bunlong Van – Rubyist/Rails Developer Mail: bunlong.van@gmail.com Blog: http://geekhmer.github.io
  • 2. Cover - What is Rspec? - RSpec features - RSpec in action - Stubs & Mocks - Stubs & Mocks using RSpec
  • 3. What is RSpec ? - Testing framework for Ruby on Rails. - Replacement for RoR built-in testing tool.
  • 4. TestUnit class Calculator < Test::Unit::TestCase def test_addition assert_equal(8, Calculator.new(6, 2).addition) end def test_subtraction assert_same(4, Calculator.new(6, 2).subtraction) end end
  • 5. RSpec desribe Calculator do let(:calculator) { Calculator.new(6,2) } it "should return 8 when adding 6 and 2" do calculator.addition.should eql(8) end it "should return 4 when subtracting 2 from 6" do calculator.subtraction.should eql(4) end end
  • 6. RSpec basics describe MyClass do # creates initial scope before do @object = MyClass.new end describe "#some_method" do # creates new scope it "should ..." do @object.should ... end context "when authorized" do # creates new scope before do @object.authorized = true end
  • 7. RSpec basics (Con.) it "should ..." do @object.should ... end end context "when not authorized" do # creates new scope it "should ..." do @object.should ... end end end it "should ..." do pending "Fix some model first" # creates pending test end end
  • 8. Why RSpec? - Readability - Tests documentation and failure messages
  • 9. Readability describe Campaign do it "should be visible by default" do campaign.should be_visible end it "should have performances visible by default" do campaign.performances_visible.should be_true end it "should not be published at start" do campaign.should_not be_published end
  • 10. Readability (Con.) it "should not be ready to publish at start - without performances, etc" do campaign.should_not be_ready_to_publish end describe "#allowed_performance_kinds" do it "should allow all by default" do campaign.allowed_performance_kinds.should == Performance.kinds end end end
  • 11. Tests documentation and failure messages
  • 12. When tests output matter - Built-in profiler - Test run filters - Conventions - Built-in matchers
  • 14. Test run filters def old_ruby RUBY_VERSION != "1.9.2" end describe TrueClass do it "should be true for true", :if => old_ruby do true.should be_true end it "should be true for String", :current => true do "".should be_true end
  • 15. Test run filters (Cons.) it "should be true for Fixnum" do 0.should be_true end end
  • 17. Built-in matchers target.should satisfy {|arg| ...} target.should_not satisfy {|arg| ...} target.should equal <value> target.should not_equal <value> target.should be_close <value>, <tolerance> target.should_not be_close <value>, <tolerance> target.should be <value> target.should_not be <value> target.should predicate [optional args] target.should be_predicate [optional args] target.should_not predicate [optional args] target.should_not be_predicate [optional args] target.should be < 6 target.should be_between(1, 10)
  • 18. Built-in matchers (Cons.) target.should match <regex> target.should_not match <regex> target.should be_an_instance_of <class> target.should_not be_an_instance_of <class> target.should be_a_kind_of <class> target.should_not be_a_kind_of <class> target.should respond_to <symbol> target.should_not respond_to <symbol> lambda {a_call}.should raise_error lambda {a_call}.should raise_error(<exception> [, message]) lambda {a_call}.should_not raise_error lambda {a_call}.should_not raise_error(<exception> [, message])
  • 19. Built-in matchers (Cons.) proc.should throw <symbol> proc.should_not throw <symbol> target.should include <object> target.should_not include <object> target.should have(<number>).things target.should have_at_least(<number>).things target.should have_at_most(<number>).things target.should have(<number>).errors_on(:field) expect { thing.approve! }.to change(thing, :status) .from(Status::AWAITING_APPROVAL) .to(Status::APPROVED) expect { thing.destroy }.to change(Thing, :count).by(-1)
  • 20. Problems ? - Hard to learn at the beginning - Routing tests could have more detailed failure messages - Rails upgrade can break tests compatibility
  • 21. RSpec in action - Model specs (placed under spec/models director) - Controller specs (placed under spec/controllers directory) - Helper specs (placed under spec/helpers directory) - View specs (placed under spec/views directory) - Routing specs (placed under spec/routing directory)
  • 22. Model specs describe Campaign do it "should be visible by default" do campaign.should be_visible end it "should have performances visible by default" do campaign.performances_visible.should be_true end it "should not be published at start" do campaign.should_not be_published end
  • 23. Model specs (Cons.) it "should not be ready to publish at start - without performances, etc" do campaign.should_not be_ready_to_publish end describe "#allowed_performance_kinds" do it "should allow all by default" do campaign.allowed_performance_kinds.should == Performance.kinds end end end
  • 24. Controller specs describe SessionsController do render_views describe "CREATE" do context "for virtual user" do before do stub_find_user(virtual_user) end it "should not log into peoplejar" do post :create, :user => {:email => virtual_user.email, :password => virtual_user.password } response.should_not redirect_to(myjar_dashboard_path) end end
  • 25. Controller specs (Cons.) context "for regular user" do before do stub_find_user(active_user) end it "should redirect to myjar when login data is correct" do post :create, :user => {:email => active_user.email, :password => active_user.password } response.should redirect_to(myjar_dashboard_path) end end end end
  • 26. Helper specs describe CampaignsHelper do let(:campaign) { Factory.stub(:campaign) } let(:file_name) { "meldung.jpg" } it "should return the same attachment URL as paperclip if there is no attachment" do campaign.stub(:featured_image_file_name).and_return(nil) helper.campaign_attachment_url(campaign, :featured_image). should eql(campaign.featured_image.url) end it "should return the same attachment URL as paperclip if there is attachment" do campaign.stub(:featured_image_file_name).and_return(file_name)
  • 27. Helper specs (Cons.) helper.campaign_attachment_url(campaign, :featured_image). should eql(campaign.featured_image.url) end end
  • 28. View specs # view at views/campaigns/index.html.erb <%= content_for :actions do %> <div id="hb_actions" class="browse_arena"> <div id="middle_actions"> <ul class="btn"> <li class="btn_blue"><%= create_performance_link %></li> </ul> </div> </div> <% end %> <div id="interest_board_holder"> <%= campaings_wall_template(@campaigns) %> </div>
  • 29. View specs (Cons.) # spec at spec/views/campaigns/index.html.erb_spec.rb describe "campaigns/index.html.erb" do let(:campaign) { Factory.stub(:campaign) } it "displays pagination when there are more than 20 published campaigns" do assign(:campaigns, (1..21).map { campaign }. paginate(:per_page => 2) ) render rendered.should include("Prev") rendered.should include("Next") end end
  • 30. Routing specs describe "home routing", :type => :controller do it "should route / to Home#index" do { :get => "/" }.should route_to(:controller => "home", :action => "index", :subdomain => false) end it "should route / with subdomain to Performances::Performances#index do { :get => "http://kzkgop.test.peoplejar.net" }. should route_to(:namespace => nil, :controller => "performances/performances", :action => "index") end end
  • 31. Routing specs (Cons.) describe "error routing", :type => :controller do it "should route not existing route Errors#new" do { :get => "/not_existing_route" }.should route_to(:controller => "errors", :action => "new", :path => "not_existing_route") end End describe "icebreaks routing" do it "should route /myjar/icebreaks/initiated to Icebreaks::InitiatedIcebreaks#index" do { :get => "/myjar/icebreaks/initiated" }.should route_to(:controller => "icebreaks/initiated_icebreaks", :action => "index") end end
  • 32. Routing specs (Cons.) describe "admin routing" do it "should route /admin to Admin::Base#index" do { :get => "/admin" }.should route_to(:controller => "admin/welcome", :action => "index") end end
  • 34. Back to unit test assumptions - A unit is the smallest testable part of an application - The goal of unit testing is to isolate each part of the program and show that the individual parts are correct - Ideally, each test case is independent from the others
  • 35. you.should use_stubs! - Isolate your unit tests from external libraries and dependencies - Propagate skinny methods which has low responsibility - Single bug should make only related tests fail - Speed up tests
  • 37. Are there any problems ? - Writing test is more time consuming - Need to know stubbed library internal implementations - Need to write an integration test first
  • 38. Stubs in action User.stub(:new) # => nil User.stub(:new).and_return(true) user_object = User.new user_object.stub(:save).and_return(true) User.stub(:new).and_return(user_object) user_object.stub(:update_attributes).with(:username => "test"). and_return(true) User.stub(:new).and_return(user_object) User.any_instance.stub(:save).and_return(true) # User.active.paginate User.stub_chain(:active, :paginate).and_return([user_object])
  • 39. Stubs in action User.stub(:new) # => nil User.stub(:new).and_return(true) user_object = User.new user_object.stub(:save).and_return(true) User.stub(:new).and_return(user_object) user_object.stub(:update_attributes).with(:username => "test"). and_return(true) User.stub(:new).and_return(user_object) User.any_instance.stub(:save).and_return(true) # User.active.paginate User.stub_chain(:active, :paginate).and_return([user_object])
  • 40. Stubs in action (Cons.) user_object.stub(:set_permissions).with(an_instance_of(String), anything).and_return(true) user_object.unstub(:set_permissions) # user_object.set_permissions("admin", true) # => true (will use stubbed method) # user_object.set_permissions("admin") # => false (will call real method)
  • 41. Mocks in action User.should_receive(:new) # => nil User.should_receive(:new).and_return(true) User.should_not_receive(:new) user_object = User.new user_object.should_receive(:save).and_return(true) User.stub(:new).and_return(user_object) user_object.should_receive(:update_attributes). with(:username => "test").and_return(true) User.stub(:new).and_return(user_object) User.any_instance.should_receive(:save).and_return(true) # !
  • 42. Mocks in action (Cons.) user_object.should_receive(:update_attributes).once # default user_object.should_receive(:update_attributes).twice user_object.should_receive(:update_attributes).exactly(3).times user_object.should_receive(:set_permissions). with(an_instance_of(String), anything) # user_object.set_permissions("admin", true) # Success # user_object.set_permissions("admin") # Fail
  • 43. What's the difference between Stubs and Mocks - Mocks are used to define expectations and verify them - Stubs allows for defining eligible behavior - Stubs will not cause a test to fail due to unfulfilled expectation
  • 44. In practice - Stub failure describe ".to_csv_file" do it "should generate CSV output" do User.stub(:active).and_return([user]) User.to_csv_file.should == "#{user.display_name},#{user.email}n" end end
  • 45. In practice - Mock failure describe "#facebook_uid=" do it "should build facebook setting instance if not exists when setting uid" do user.should_receive(:build_facebook_setting).with(:uid => "123") user.facebook_uid = "123" end end