Friday, June 25, 2010

let, its, and subject

We're going to refactor a spec to a more concise size.


First here is our starting point:


describe Foobar do
   before(:each) do
      @foobar = Foobar.new
   end
   
   it "should not be nil"
      @foobar.should_not be_nil
   end
   
   describe "#length" do
      before(:each) do
         @length = @foobar.length
      end
    
      it "should == 10" do
         @length.should == 10
      end
   end
end


The above example uses 15 lines of code. Lets see if we can do better.


First we're going to replace the 'before' blocks with 'let' blocks.
The 'let' block returns an evaluated block. It really helps you define
players in your spec.


describe Foobar do
   let(:foobar) {Foobar.new}
   
   it "should not be nil"
      foobar.should_not be_nil
   end
   
   describe "#length" do
      let(:length) {foobar.length}
    
      it "should == 10" do
         length.should == 10
      end
   end
end


That's a bit better. We are now at 11 lines of code.
But, we can do better.

We're going to use 'subject' block. This allows us to call
'should' right within the block. We're also going to use an 'its' block.
The 'its' block will return to us the value of the message retrieved represented
by the symbol we passed to it.


describe Foobar do
   subject {Foobar.new}
   
   it {should_not be_nil}
   its(:length) {should == 10}
end


Very good. We have brought it down to 5 lines.

What does the specdoc output look like?

Here it is:


Foobar
- should not be nil
Foobar length
- should == 10

No comments: