RSpec: What, How and Why
Upcoming SlideShare
Loading in...5
×
 

RSpec: What, How and Why

on

  • 3,592 views

BDD with RSpec.

BDD with RSpec.

Statistics

Views

Total Views
3,592
Slideshare-icon Views on SlideShare
3,574
Embed Views
18

Actions

Likes
4
Downloads
54
Comments
0

3 Embeds 18

http://www.slideshare.net 13
http://www.linkedin.com 4
https://www.linkedin.com 1

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • Introduced by Dan North in 2006Found that training people in TDD was hard since the process lacked direction.Mixed DDD(Domain Driven Design) + TDDStart with the requirements. Work inwards.The Tools:A change in language (tests -> specs)Interaction-Based TestingDescriptive Tests
  • The ProcessAs opposed to state-based testing(Test::Unit)Mock all immediate neighbors of a unit.Define Expectations of the mock objectsRun the unit & Check if expectations are metObservationsTests get too intimate with implementationGood/Bad thing?Test behavior not state.Faster if done_right?A true Unit Test – Complete isolation of the unitAssumes that the interface is constant and the state is mutable.
  • 1246 context "when not available in cache" do 1247 before do 1248 @slideshow= Factory(:slideshow, :user_id => @user.id) 1249 @tag_det= Factory(:tag_det, :slideshow => @slideshow) 1250 end 1251 it "should return it from db" do 1252 @user.tags.should ==[@tag_det] 1253 end 1254 1255 it "should add the data to cache" do 1256 Cache.should_receive(:put).with("TagDet:#{@user.id}", [@tag_det], anything) 1257 @user.tags1258 end 1259 end 1260 end

RSpec: What, How and Why RSpec: What, How and Why Presentation Transcript

  • RSpec
    The What, How and Why?
  • What?
  • What is Rspec?
    A BDD Framework for Ruby
  • What is Rspec?
    A BDD Framework for Ruby
    A testing framework that supports BDD
  • What is BDD
    /[T|B]DD/: Just Tests ... Right?
  • /[T|B]DD/: Just Tests ... Right?
  • 100% Code Coverage is Good.Good Code + 100% Coverage is Better.
    Feel Free make whatever you want out of the above picture
  • Enter BDD
    Dan North(ThoughtWorks)
    Teaching TDD was hard
    TDD needed Direction
  • The Tools of BDD
    Change Of Focus
    Interaction-Based Testing
    A Ubiquitous Language
  • Change of Focus
    Tests have a tendency of loosing focus of what we’re meant to be building. Too low level.
    test_cases.each {|case| case.shouldadd_business_value}
    tests which describe domain specific functions => specs
    Keeps focus. Gives direction.
  • Interaction-Based Testing
    As opposed to state-based testing
    OOP design principles:
    Object exposes methods which are the only thing that touch its internal state.
    Any change in state requires a method call. SO:
    Just test that the call is made. Mock out all neighboring objects.
    A true UNIT test.
  • Is that a Bad thing?<wait for the onslaught>
    HOLD ON!
    Doesn’t that mean that my tests are tightly coupled with my implementation?
  • HOW?
  • How Do I use Rspec (with rails)?
  • How Do I use Rspec (with rails)?
    gem install rspecrspec-rails
  • How Do I use Rspec (with rails)?
    gem install rspecrspec-rails
    ./script/generate rspec
  • The Rspec Files
  • A Word about Factories
    A easy-to-maintain replacement for fixtures
    (Finally some code!)
    More about creating your own strategies at the
    end of this presentation
  • spec_helper.rb
    Loaded at the beginning of ever spec file
    Put methods that can be used by all specs here.
  • Examples
    The equivalent of a unit test in RSpec
  • The Syntax
    describe “Unit#something” do
    before(:each) do
    @unit= Unit.new(params)
    end
    it “should return something” do
    @unit.something.should == ‘something’
    end
    end
  • The Syntax
    describe “Unit#something” do
    before(:each) do
    @unit= Unit.new(params)
    end
    it “should return something” do
    @unit.something.should == ‘something’
    end
    end
    EXAMPLE
  • The Syntax
    describe “Unit#something” do
    before(:each) do
    @unit= Unit.new(params)
    end
    it “should return something” do
    @unit.something.should == ‘something’
    end
    end
  • The Syntax
    context “Unit#something” do
    before(:each) do
    @unit= Unit.new(params)
    end
    specify “should return something” do
    @unit.something.should == ‘something’
    end
    end
  • The Syntax
    describe “Unit#something” do
    before(:each) do
    @unit= Unit.new(params)
    end
    it “should return something” do
    @unit.something.should == ‘something’
    end
    end
  • The Syntax
    describe “Unit#something” do
    before(:each) do
    @unit= Unit.new(params)
    end
    it “should return something” do
    @unit.something.should == ‘something’
    end
    end
  • The Syntax
    describe “Unit#something” do
    before(:each) do
    @unit= Unit.new(params)
    end
    it “should return something” do
    @unit.something.should == ‘something’
    end
    end
  • The Syntax
    describe “Unit#something” do
    before(:each) do
    @unit= Unit.new(params)
    end
    it “should return something” do
    @unit.something.should == ‘something’
    end
    end
  • The mocking/stubbing framework
    object.stub!(:foo => ‘bar’, :one => 1)
    object.stub!(:foo).and_return(‘bar’)
    mock_object= mock/mock_model(Klass, espectations= {:foo => ‘bar’})
    mock_object.foo #=> ‘bar’
    Tool for Interaction Testing:
    mock_object.should_receive(:message).exactly(n).times.with(params).and_return(val)
    Each of the methods in that chain take many different options. Ref: Links
    Raises error if the message isn’t received & with the parameters specified & with the correct freq.
  • Mocks Aren’t Stubs
    Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what's programmed in for the test. Stubs may also record information about calls, such as an email gateway stub that remembers the messages it 'sent', or maybe only how many messages it 'sent'.
    Mocks are […] objects pre-programmed with expectations which form a specification of the calls they are expected to receive.
    -Martin Fowler
  • Functional Tests(Controller Examples)
    Isolate controllers from the models(mocks)
    Big difference from Rails Functional Testing:
    Also isolate it from the views.
    Integration is possible with integrate_views
  • Controller specific Expectations
    Response Expectations
    should be_success
    should render_template
    should be_redirect
    should redirect_to
    response.[assigns|flash|sessions]
    Routing Expectations
    route_for(:controller => …, :action => …).should == /…/…/
    params_from(
    :get,"/hello/world").should ==
    {:controller=>"hello”
    ,:action => "world"}
  • View Examples
    Again<Yawn> Isolation is key.
    # example
    article = mock_model(Article)
    article.should_receive(:author).and_return("J”)
    article.should_receive(:text).and_return("this is the text of the article")
    assigns[:article] = article
    assigns[:articles] = [article]
    # flash and params are also available
    # template
    <% for article in @articles -%> <!-- etc -->
  • View Specific Expectations
    response.shouldhave_tag
    #examples
    response.shouldhave_tag('div#interesting_div‘, contents)
    # Contents can be Regexp or String
    response.shouldhave_tag("input[type=?][checked=?]", 'checkbox', 'checked')
    response.shouldhave_tag('ul') do
    with_tag('li', 'list item 1')
    with_tag('li', 'list item 2')
    with_tag('li', 'list item 3')
    end
  • Exercise
  • My Spec
  • WHY?
  • The RSpec Philosophy
    Clarity over Cleverness
    Completely isolate the unit under test
    i.e. Mock Everything
  • Pros and Cons
    More descriptive code == more lines of code
    Not very DRY
    Tight coupling of test and implementation.
    Easily understandable tests
    True unit tests
    Interoperability with other testing frameworks
  • Interaction Testing is a Guideline
    Not a rule
    Depends on what you are testing.
    Remember: Usually leads to better OO Design not always better tests.
  • Good News
    Rspec doesn’t force IBT on you
    Write tests that work best for you.
  • If we’re doing SBT with Rspec.Why not stick to Test::Unit?
    OPTIONS
    RSpec is versatile. Can do everything that Test::Unit does and then some.
    Undoubtedly better for adding new functionality
  • Why RSpec?
    RSpec is not just about RSpec. It's about BDD. It's about encouraging conversation about testing and looking at it in different ways. It's about illuminating the design, specification, collaboration and documentation aspects of tests, and thinking of them as executable examples of behaviour. You can do this all without RSpec, but RSpec aims to help with innovations like:
    strings as example names
    pending examples
    nested groups for flexible organization
    should[_not] + matchers (inspired by hamcrest - a java library)
    one matcher supports both positive and negative expectations
    improved failure messages
    flexible/readable/customizable output formats
    built-in mocking framework
    plain text scenarios (now in Cucumber)
    - David Chelimsky(RSpec lead developer)
  • More Quotes
    The problem I have with TDD is that its mindset takes us in a different direction... a wrong direction. – Dave Astels(RSpec Creator)
  • Thank You!
    Questions.
    Pleeeeease!!
  • Links
    http://blog.dannorth.net/introducing-bdd/
    http://benpryor.com/blog/2007/01/16/state-based-vs-interaction-based-unit-testing/
    http://rspec.info
    http://rspec.rubyforge.org/rspec/1.2.6/
    Why Rspec? [http://www.ruby-forum.com/topic/184933]
    Full List of expectation definition options
    http://asciicasts.com/episodes/157-rspec-matchers-macros