5: Red: should and should_not

[~/local/src/ruby/LPP/rspec_examples/rpcalculator(master)]$ cat spec/math/rpcalc_spec.rb 
#require File.join(File.dirname(__FILE__), "/../spec_helper")
require "spec_helper"
module Math
  describe RPCalc do
    before :each do
      @c = Math::RPCalc.new
    end

    context "When an erroneous input is given" do
      before :each do
        @e = proc { @c.calc('a') }
      end
      it "must raise an exception" do
        expect { @e[] }.to raise_error(SyntaxError)
        expect { @e[] }.to raise_error("Error. found 'a'. Expected number or operator")
      end
    end

    context "When a correct input is given" do
      it "must compute the answer" do
        r = @c.calc('2 3 + 4 *')
        r.should eq 20
        @c.stack.should eq []
      end
    end

  end    # RPCalc
end      # Math

RSpec achieves a high level of expressiveness and readability by exploiting open classes in Ruby to add the methods should() and should_not( ) to every object in the system. Each method accepts either a matcher or a Ruby expression using a specific subset of Ruby operators.

A matcher is an object that tries to match against an expected outcome.

Let’s take a look at an example using the equal matcher, which you can access through the method eq:

       r.should eq 20
When the Ruby interpreter encounters this line, it begins by evaluating eq 20.

This is an RSpec method that returns a matcher object configured to match for equality with the value 20. The matcher then becomes the argument to r.should.

Behind the scenes, the should( ) method calls matcher.matches?, passing self (the result object) as the argument. Because should( ) is added to every object, it can be any object. Similarly, the matcher can be any object that responds to matches?(object).

If matches?(self) returns true, then the expectation is met and execution moves on to the next line in the example.

If matches?(self) returns false, should( ) asks the matcher for a failure message and raises an ExpectationNotMetError with that message.

[~/local/src/ruby/LPP/rspec_examples/rpcalculator(master)]$ rake spec
rspec -Ilib -Ispec spec/math/rpcalc_spec.rb

Math::RPCalc
  When an erroneous input is given
    must raise an exception
  When a correct input is given
    must compute the answer (FAILED - 1)

Failures:

  1) Math::RPCalc When a correct input is given must compute the answer
     Failure/Error: r = @c.calc('2 3 + 4 *')
     SyntaxError:
       Error. found '2'. Expected number or operator
     # ./lib/math/rpcalc.rb:12:in `block in calc'
     # ./lib/math/rpcalc.rb:11:in `each'
     # ./lib/math/rpcalc.rb:11:in `calc'
     # ./spec/math/rpcalc_spec.rb:21:in `block (3 levels) in <module:Math>'

Finished in 0.00244 seconds
2 examples, 1 failure

Failed examples:

rspec ./spec/math/rpcalc_spec.rb:20 # Math::RPCalc When a correct input is given must compute the answer
rake aborted!

Casiano Rodriguez León 2015-01-07