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).

Rémi Prévost

February 28, 2013
Tweet

More Decks by Rémi Prévost

Other Decks in Technology

Transcript

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

    View full-size slide

  2. Rémi Prévost
    Freelance Web Developer

    View full-size slide

  3. • RSpec
    • RSpec + Rails

    View full-size slide


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

    View full-size slide

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

    View full-size slide

  6. Get Started
    Let’s do it live!

    View full-size slide

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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  10. [1, 2, 3].should_not be_empty
    # [1, 2, 3].empty?
    { foo: "bar" }.should have_key(:foo)
    # { foo: "bar" }.has_key?(:foo)

    View full-size slide

  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

    View full-size slide

  12. Helpers
    Features
    • Subjects
    • Let
    • Hooks
    • Contexts

    View full-size slide

  13. Subjects
    Features • Helpers
    • Avoid repetitive code

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  18. Let
    Features • Helpers
    • Lazy-evaluated blocks
    • Evaluated once for each example

    View full-size slide

  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

    View full-size slide

  20. Hooks
    Features • Helpers
    • Before + after
    • :each, :all, :suite

    View full-size slide

  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

    View full-size slide

  22. Contexts
    Features • Helpers
    • Groups of examples
    • Shared subject, lets & hooks

    View full-size slide

  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

    View full-size slide

  24. Mocks
    Features
    • Method stubbing
    • Message expectations

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  27. • RSpec
    • RSpec + Rails

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  30. Thank you!
    Comments? Questions?
    @remi

    View full-size slide