【问题标题】:How to refactor RSpec tests for API如何重构 API 的 RSpec 测试
【发布时间】:2012-09-24 22:33:39
【问题描述】:

我对基于 Sinatra 的 API 进行了一系列 RSpec 测试,并希望重构它们以使其更简单并减少重复。

这是一个路由测试示例:

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

每个测试都将使用相同的基本 URL,具有相同的会话数据,唯一的区别是参数以及响应应该是什么。每个路由至少有 4 个测试(GET、POST、PUT、DELETE),通常更多。

有没有办法让这些测试更易于管理?

【问题讨论】:

    标签: ruby rspec sinatra rack-test


    【解决方案1】:

    无需借助元编程,您可以使用嵌套的describe 块来仅覆盖您想要的参数:

    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
    

    【讨论】:

    • +1 对于所提供的信息,我认为这是最好的方法。
    • 目前我对路由使用嵌套的 describe 块,然后是它们下面的测试,但正如您所做的那样,将路由抽象为 before 块是有意义的。谢谢!
    • 我已经将 before 过滤器移到了我最外层的描述 API 的描述中,并允许每个 POST/GET/PUT/DELETE 块描述它正在使用的 URL,以便轻松指定 @ 987654323@。非常感谢您的想法!
    【解决方案2】:

    不知道这是否有效,但它可以让您了解您可以做什么

    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
    

    更新

    再次阅读您的问题让我意识到这不是您真正要求的。如果它根本没有帮助告诉我,所以我删除它。

    【讨论】:

    • 理想情况下我会测试不同的响应,但我喜欢使用 each 块来压缩测试的想法。
    • 是的,但是对于您的情况,您还可以将数组中的参数放在像[{method: 'post', params: {...}}, ...] 这样的散列中,这样会变得混乱且难以辨认。雷纳托的回答似乎很好。也许在你可以尝试重构它之后
    猜你喜欢
    • 2019-03-09
    • 2013-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-02
    相关资源
    最近更新 更多