Search code examples
rubyrspecsinatrarack-test

How to refactor RSpec tests for API


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?


Solution

  • 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