【问题标题】:Rails: multiple get requests in a single functional testRails:单个功能测试中的多个获取请求
【发布时间】:2012-12-12 04:05:53
【问题描述】:

我想在相同的测试中对一些获取请求进行分组,但我得到了不稳定的行为。我有以下两个测试:

test 'index for local seller (same site)' do
  seller = FactoryGirl.create :seller, business_site: @open_or.business_site
  get :index, nil, {user_id: seller.to_param }
  assert_select "table#order_requests tr##{@controller.view_context.dom_id @open_or}"
end
test 'index for local seller (different site)' do
  seller = FactoryGirl.create :seller_local
  get :index, nil, {user_id: seller.to_param }
  assert_select "table#order_requests tr##{@controller.view_context.dom_id @open_or}", false
end

我想在一个测试中组合它,但如果我这样做,第二个断言将错误地失败(预计正好 0 个元素匹配“table#order_requests tr#order_request_1000244799”,找到 1.)。我真的不明白为什么?第二个“获取”调用可能无法正确重置某些内容。我寻找“重置”请求的方法但没有成功。

相关:making two requests to the same controller in rails integrations specs

【问题讨论】:

    标签: ruby-on-rails functional-testing


    【解决方案1】:

    我在功能测试(与集成相反)中注意到的一个重要区别是控制器的状态似乎不会在请求之间重置,这可能会导致意外结果。例如,考虑这个(人为的)控制器:

    class ThingyController < ApplicationController
      def one 
        @thingy = Thingy.first
        render :nothing => true
      end 
    
      def two 
        render :nothing => true
      end 
    end
    

    动作“一”设置@thingy,而动作“二”不设置。但是,此功能测试失败:

    test "thingy should not exist in second request" do
      get :one
      assert_not_nil assigns(:thingy), "thingy should exist in get_one"
      get :two
      assert_nil assigns(:thingy), "thingy should be absent in get_two"
    end
    

    大概是因为第一个请求中的@thingy 在测试方法期间作为实例变量保留在控制器中。

    虽然您当然可以在一个测试中进行多个 get/put/etc 调用,但我认为它们并非旨在为每个测试方法测试多个操作。根据Rails API TestCase docs

    功能测试允许您在每个测试中测试单个控制器操作 方法。这不应与集成测试混淆(参见 ActionDispatch::IntegrationTest),更像是“故事” 可能涉及多个控制器和多个动作(即多个 不同的 HTTP 请求)。

    如果您真的希望将这两个操作结合起来,也许集成测试会是更好的方法。

    【讨论】:

      【解决方案2】:

      好吧,你没有展示组合测试,也没有展示什么失败,所以它几乎是在黑暗中工作,但为了组合这些测试,我可能会做类似的事情

      test 'index for seller (same site)' do
        first_seller = FactoryGirl.create :seller, business_site: @open_or.business_site
        get :index, nil, {user_id: first_seller.to_param }
        assert_select "table#order_requests tr##{@controller.view_context.dom_id @open_or}"
        second_seller = FactoryGirl.create :seller_local
        get :index, nil, {user_id: second_seller.to_param }
        assert_select "table#order_requests tr##{@controller.view_context.dom_id @open_or}", false
      end
      

      以上假设您的单独测试通过了,如果是这样,我没有理由明白为什么这不起作用(但我不太擅长在黑暗中看东西)

      顺便说一句,测试不会错误地失败,测试失败总是有原因的,通常是有效的失败或经过考虑不周的测试,无论哪种方式,这是程序员引入的错误而不是测试错误全部!

      更新 - 根据 railscast http://railscasts.com/episodes/275-how-i-test,使用 save_and_open_page 测试失败时,在浏览器中查看网页中的实际内容

      组合测试和单独测试之间的区别在于,每次测试之间数据库都会被清除,因此您的第一个卖家在组合测试中仍会存在于数据库中,但在单独运行时不会存在于第二个测试中测试

      【讨论】:

      • 这正是我所说的组合它们的测试。如果我运行此测试,它将失败(预计正好 0 个元素与“table#order_requests tr#order_request_1000244799”匹配,找到 1 个。)同时保持它们分开通过。
      • @gamov 请将未通过的组合测试粘贴到原始问题中。
      • 但这是一个有效的失败吗?你在你的代码中发现了一个错误吗?当您根据我链接到的 railscast 保存_and_open_page 时,您在浏览器中看到什么
      • 这是一个FUNCTIONAL测试,不是INTEGRATION测试,这里没有capybara。
      • 第二次测试前你有没有尝试过清空你的数据库?似乎您的测试告诉您存在订单请求,而您并不期望它。那为什么会这样呢?
      【解决方案3】:

      如果您有很多地方可以区分“相同站点”和“不同站点”行为(或任何其他两层行为),那么在 test_helper.rb 中添加一个简单地添加两者的辅助方法可能是有意义的为您测试:

      def only_for_same_site_should(description, &action)
        class_eval do
          test "should #{description} if same site" do
            action.call(self, FactoryGirl.create :seller, true)
          end
          test "should NOT #{description} if different site" do
            action.call(self, FactoryGirl.create :seller_local, false)
          end
        end
      end
      

      然后像这样在控制器测试类中使用它:

      only_for_same_site_should("have tag order_requests in index") do |test, seller, same_site|
        test.get :index, nil, {user_id: seller.to_param}
        assert_select "table#order_requests tr##{@controller.view_context.dom_id @open_or}", same_site
      end
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多