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

RSpec: natural behavior testing for Rails applications

RSpec: natural behavior testing for Rails applications

Talk given on February 28 2013 at ConFoo 2013 (Montréal).

8c4cee1129bc11fbe9a0b9379dce2cb1?s=128

Rémi Prévost

February 28, 2013
Tweet

Transcript

  1. Rémi Prévost — ConFoo 2013 RSpec: natural behavior testing for

    Rails applications
  2. Rémi Prévost Freelance Web Developer

  3. • RSpec • RSpec + Rails

  4. “ RSpec is a Behaviour-Driven Development tool for Ruby programmers

  5. • Test for behavior not end results • Natural language

    Principles
  6. Get Started Let’s do it live!

  7. • Expectations • Helpers • Mocks (rspec-mocks) Features

  8. Expectations Features • Test the behavior of objects or blocks

    • Objects should or should_not have a certain behavior • We expect blocks to trigger a certain behavior
  9. "foo".should eql "foo" # "foo" == "foo" Array.new.should be_an_instance_of(Array) #

    Array.new.instance_of?(Array) "foo".should_not respond_to(:to_a) # "foo".respond_to?(:to_a) [1, 2, 3].should have(3).items # [1, 2, 3].size == 3
  10. [1, 2, 3].should_not be_empty # [1, 2, 3].empty? { foo:

    "bar" }.should have_key(:foo) # { foo: "bar" }.has_key?(:foo)
  11. expect { 42/0 }.to raise_error(ZeroDivisionError) # &block.call rescue ZeroDivisionError items

    = [1, 2, 3, 4] expect { items.clear }.to change{ items.size }.from(4).to(0) # &expectation.call == 4 # &block.call # &expectation.call == 0
  12. Helpers Features • Subjects • Let • Hooks • Contexts

  13. Subjects Features • Helpers • Avoid repetitive code

  14. describe Post do it("should not be published") do Post.new.should_not be_published?

    end it("should have a default author") do Post.new.author.should eql "remi" end end class Post < OpenStruct def published? self.published == true end def author self.author || "remi" end end
  15. describe Post do subject { Post.new } it { should_not

    be_published? } its(:author) { should eql "remi" } end class Post < OpenStruct def published? self.published == true end def author self.author || "remi" end end
  16. describe Post do it { should_not be_published? } its(:author) {

    should eql "remi" } end class Post < OpenStruct def published? self.published == true end def author self.author || "remi" end end
  17. describe Post do subject { Post.new(author: "jack") } it {

    should_not be_published? } its(:author) { should eql "jack" } end class Post < OpenStruct def published? self.published == true end def author self.author end end
  18. Let Features • Helpers • Lazy-evaluated blocks • Evaluated once

    for each example
  19. describe Post do subject { Post.new(author: user) } let(:user) {

    User.new(first_name: "Rémi") } its(:author_name) { should eql user.first_name } end class Post < OpenStruct def author_name self.author.first_name end end
  20. Hooks Features • Helpers • Before + after • :each,

    :all, :suite
  21. describe Post do before :all do puts "Running tests for

    Post..." end before :each do ActionMailer::Base.deliveries.clear DatabaseCleaner.clear end it { should_not be_published } its(:author) { should be_nil } end
  22. Contexts Features • Helpers • Groups of examples • Shared

    subject, lets & hooks
  23. describe Post do describe :initialize do subject { Post.new(parameters) }

    context "with empty parameters" do let(:parameters) { {} } it { should_not be_valid? } end context "with valid parameters" do let(:parameters) { { title: "Hello world." } } it { should be_valid? } end end end
  24. Mocks Features • Method stubbing • Message expectations

  25. describe Post do subject { Post.new(:author_id => 4) } describe

    :author do before do a = OpenStruct.new(full_name: "Rémi Prévost") Author.stubs(:find).and_return(a) end its(:author) { should eql "Rémi Prévost" } end end class Post < OpenStruct def author Author.find(self.author_id).full_name end end
  26. describe Post do subject { Post.new(:author_id => 4) } describe

    :author do before do a = OpenStruct.new(full_name: "Rémi Prévost") Author.should_receive(:find).with(4).and_return(a) end its(:author) { should eql "Rémi Prévost" } end end class Post < OpenStruct def author Author.find(self.author_id).full_name end end
  27. • RSpec • RSpec + Rails

  28. • Get Started • Models (unit) • Controllers + Views

    (integration) RSpec + Rails
  29. Let’s do it live! RSpec + Rails

  30. Thank you! Comments? Questions? @remi