Refactoring Rspec specs

Posted by Steve Weet on Stack Overflow See other posts from Stack Overflow or by Steve Weet
Published on 2010-04-29T14:43:32Z Indexed on 2010/04/29 14:47 UTC
Read the original article Hit count: 148

Filed under:
|
|
|

I am trying to cleanup my specs as they are becoming extremely repetitive.

I have the following spec

  describe "Countries API" do 
    it "should render a country list" do
      co1 = Factory(:country)
      co2 = Factory(:country)
      result = invoke :GetCountryList, "empty_auth"

      result.should be_an_instance_of(Api::GetCountryListReply)
      result.status.should be_an_instance_of(Api::SoapStatus)
      result.status.code.should eql 0
      result.status.errors.should be_an_instance_of Array
      result.status.errors.length.should eql 0
      result.country_list.should be_an_instance_of Array
      result.country_list.first.should be_an_instance_of(Api::Country)
      result.country_list.should have(2).items
    end
    it_should_behave_like "All Web Services"
    it "should render a non-zero status for an invalid request"
  end

The block of code that checks the status will appear in all of my specs for 50-60 APIs. My first thought was to move that to a method and that refactoring certainly makes things much drier as follows :-

def status_should_be_valid(status)
    status.should be_an_instance_of(Api::SoapStatus)
    status.code.should eql 0
    status.errors.should be_an_instance_of Array
    status.errors.length.should eql 0
end

describe "Countries API" do 
    it "should render a country list" do
      co1 = Factory(:country)
      co2 = Factory(:country)
      result = invoke :GetCountryList, "empty_auth"

      result.should be_an_instance_of(Api::GetCountryListReply)
      status_should_be_valid(result.status)
      result.country_list.should be_an_instance_of Array
      result.country_list.first.should be_an_instance_of(Api::Country)
      result.country_list.should have(2).items
    end
  end

This works however I can not help feeling that this is not the "right" way to do it and I should be using shared specs, however looking at the method for defining shared specs I can not easily see how I would refactor this example to use a shared spec.

How would I do this with shared specs and without having to re-run the relatively costly block at the beginning namely

  co1 = Factory(:country)
  co2 = Factory(:country)
  result = invoke :GetCountryList, "empty_auth"

© Stack Overflow or respective owner

Related posts about ruby

Related posts about ruby-on-rails