Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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 (http://lrug.org/meetings/2007/06/20/july-2007-meeting/). James Mead gave a talk about mocks (http://jamesmead.org/blog/2007-07-22-an-introduction-to-mock-objects-in-ruby) at the same meeting, so I didn't go into any detail there.

Tom Stuart

July 09, 2007
Tweet

More Decks by Tom Stuart

Other Decks in Programming

Transcript

  1. 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. 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”?
  3. 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
  4. 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
  5. 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
  6. A language that doesn’t affect the way you think about

    programming is not worth knowing. — Alan Perlis “ ”
  7. 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”, ...
  8. 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. “
  9. I remember thinking “if only someone had told me that!”

    more often than I thought “wow, a door has opened.”
  10. 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 ”
  11. 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)
  12. • ...to do TDD right • ...to write specs that

    also serve as intention-revealing documentation These new words make it easier and more natural...
  13. 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
  14. 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. “ ” — rspec.rubyforge.org
  15. RSpec includes many matchers. #should and #should_not take a matcher

    as an argument, and apply it to their receiver.
  16. ...and many more. (It’s easy to write your own matcher:

    any object that responds to #matches? and #failure_message will work.)
  17. 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
  18. 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
  19. • 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
  20. 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
  21. 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
  22. 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
  23. Places to start • rspec.rubyforge.org: tutorials and RDoc • script/generate

    rspec_scaffold • sample.caboo.se, etc • rspec-users