RSpec (on Rails)

RSpec (on Rails)

After much demand for a talk about RSpec from LRUG members, I stepped up to the bat. This talk introduces RSpec and shows how to use it with Rails instead of the default Test::Unit tests.

Given at the July 2007 LRUG meeting ( James Mead gave a talk about mocks ( at the same meeting, so I didn't go into any detail there.


Tom Stuart

July 09, 2007


  1. 2.

    Weasel words Who am I, anyway? Not an expert, just

    a satisfied customer. This is a distillation of public documentation. BDD & RSpec: controversial? YOU DECIDE. This is just an infomercial.
  2. 4.
  3. 7.

    1. Think of some functionality you want 2. Write a

    test for it (and watch it fail) 3. Write the code necessary to pass the test 4. Refactor Toward Deeper Insight™ 5. Goto 1 6. Profit! Test-Driven Development Is this “testing”?
  4. 8.

    WIKIPEDIA Practitioners emphasize that test-driven development is a method of

    designing software, not merely a method of testing. “ ” Test-driven development From Wikipedia, the free encyclopedia
  5. 9.

    WIKIPEDIA In linguistics, the Sapir–Whorf hypothesis states that there is

    a systematic relationship between the grammatical categories of the language a person speaks and how that person both understands the world and behaves in it. “ ” Sapir–Whorf hypothesis From Wikipedia, the free encyclopedia
  6. 10.

    WIKIPEDIA Put simply, the hypothesis argues that the nature of

    a particular language influences the habitual thought of its speakers. Different patterns of language yield different patterns of thought. “ ” Sapir–Whorf hypothesis From Wikipedia, the free encyclopedia
  7. 11.

    A language that doesn’t affect the way you think about

    programming is not worth knowing. — Alan Perlis “ ”
  8. 12.

    Test-Driven Development In proper TDD we’re not really verifying code,

    we’re specifying behaviour. But the vocabulary is all testing-oriented: • methods named “test_...” • conditions verified with “assert” • classes called “Test”, “TestCase”, ...
  9. 14.

    The deeper I got into TDD, the more I felt

    that my own journey had been less of a process of gradual mastery than a series of blind alleys. “
  10. 15.

    I remember thinking “if only someone had told me that!”

    more often than I thought “wow, a door has opened.”
  11. 16.

    I decided it must be possible to present TDD in

    a way that gets straight to the good stuff and avoids the pitfalls. My response is behaviour- driven development. — Dan North ”
  12. 17.
  13. 18.

    Behaviour-Driven Development Specify behaviour, don’t verify state. (New names for

    old TDD ideas.) Adds no technical power... ...but adds psychological power through constraints. (& technical convenience through a DSL in RSpec)
  14. 20.

    • do TDD right • write specs that

    also serve as intention-revealing documentation These new words make it easier and more natural...
  15. 24.

    Account when first created - should have a balance of

    £0 - should allow deposits Account when at overdraft limit - should not allow withdrawals Finished in 0.006646 seconds 3 examples, 0 failures
  16. 26.

    When RSpec executes specifications, it defines #should and #should_not on

    every object in the system. These methods are your entry to the magic of RSpec. “ ” —
  17. 27.

    RSpec includes many matchers. #should and #should_not take a matcher

    as an argument, and apply it to their receiver.
  18. 32.

    ...and many more. (It’s easy to write your own matcher:

    any object that responds to #matches? and #failure_message will work.)
  19. 33.
  20. 34.
  21. 35.
  22. 36.

    tom:~$ spec --color --format specdoc stack_spec.rb Stack when full -

    should be full - should not be empty - should return the top item when sent #peek - should NOT remove the top item when sent #peek - should return the top item when sent #pop - should remove the top item when sent #pop - should complain on #push (FAILED - 1) 1) 'Stack when full should complain on #push' FAILED expected StackOverflowError but nothing was raised ./stack_spec.rb:46: Finished in 0.007652 seconds 7 examples, 1 failure
  23. 37.
  24. 38.

    tom:~$ spec --color --format specdoc stack_spec.rb Stack when full -

    should be full - should not be empty - should return the top item when sent #peek - should NOT remove the top item when sent #peek - should return the top item when sent #pop - should remove the top item when sent #pop - should complain on #push Finished in 0.007514 seconds 7 examples, 0 failures
  25. 40.

    • state-based testing breaks encapsulation and is a barrier to

    refactoring • use mock objects to get away from testing state — test interactions instead • mocking everything (except the object under consideration) greatly reduces dependency and increases isolation • mocks are automatically verified when a spec finishes executing
  26. 41.

    RSpec has a built-in mocking framework. Mocking is an integral

    part of BDD, but not vice versa. You can already do this interaction-based behavioural testing with Test::Unit and Mocha (or FlexMock, or ...) These mocking frameworks can plug into RSpec too: Spec::Runner.configure do |config| config.mock_with :mocha end
  27. 44.
  28. 45.
  29. 46.

    script/generate rspec_model Account admin:boolean script/generate rspec_controller Dog bark fetch script/generate

    rspec_scaffold Post title:string body:text Spec generators: Custom expectations for models, controllers, views and helpers
  30. 49.

    Controller examples account = mock_model(Account) Account.should_receive(:find).with(37).and_return(account) response.should be_success response.should redirect_to(‘posts/1’)

    response.should render_template(‘list’) response.should have_text(‘some text’) #id, #to_param, #new_record?, #errors, #is_a?, #kind_of?, #instance_of?, #class
  31. 51.

    Places to start • tutorials and RDoc • script/generate

    rspec_scaffold •, etc • rspec-users
  32. 52.