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

Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxTier1 app
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationkaushalgiri8080
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...aditisharan08
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfjoe51371421
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEOrtus Solutions, Corp
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
 
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝soniya singh
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...soniya singh
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfkalichargn70th171
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWave PLM
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 

Recently uploaded (20)

Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanation
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdf
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need It
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 

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