How to refactor RSpec tests for API

464 Views Asked by At

I've got a series of RSpec tests for a Sinatra based API, and would like to refactor them to make them a little simpler and reduce repetition.

Here's an example a test for a route:

describe 'post /sections with empty data' do
    before do

        params = {
            :site_id    => site.id,
            :page_id    => page.id,
        }

        post '/sections', params, @session
    end

    specify { last_response.status.should == 200 }
    specify { json_response['id'].should_not be_nil }
    specify { json_response['type'].should == default_section_type }
end

Each test will be using the same base URL, with the same session data, the only difference is the parameters, and what the responses should be. There's at least 4 tests (GET, POST, PUT, DELETE) per route, and usually more.

Is there a way of making these tests more manageable?

2

There are 2 best solutions below

3
On BEST ANSWER

Without resorting to metaprogramimng, you can use nested describe blocks to override only the parameters you want:

describe "/sessions" do
  before do
    send(http_method, "/sessions", params, @session)
  end

  describe "with POST" do
    let(:http_method) { :post }

    describe "and empty data" do
      let(:params) do
        { :site_id => site.id, :page_id => page.id }
      end

      specify { last_response.status.should == 200 }
      specify { json_response['id'].should_not be_nil }
      specify { json_response['type'].should == default_section_type }
    end

    describe "with non-empty data" do
      let(:params) do
        # relevant params
      end
    end
  end

  describe "with GET" do
    let(:http_method) { :get }

    # ...
  end
end
2
On

Have no idea if this works but it can give you an idea of what you can do

describe ' /sections with empty data' do
    before(:all) do
      @params = {
            :site_id    => site.id,
            :page_id    => page.id,
        }
    end

    after(:each) do
      specify { last_response.status.should == 200 }
      specify { json_response['id'].should_not be_nil }
      specify { json_response['type'].should == default_section_type }
    end

    [:get, :post, :put, :delete].each do |http_method|
        it "works with #{http_method}" do
            send(http_method) '/sections', @params, @session
        end
    end
end

Update

Reading your question again made me realize that this is not what you actually asked for. If it doesn't help at all tell me so I delete it.