Rails:单个功能测试中的多个get请求

时间:2012-12-12 04:05:53

标签: ruby-on-rails functional-testing

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

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.)。我真的不明白为什么?第二次'get'调用可能无法正常重置某些内容。我想方设法“重置”请求但没有成功。

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

3 个答案:

答案 0 :(得分:10)

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

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调用,但我认为它们不是为每种测试方法测试多个动作而设计的。根据{{​​3}}:

  

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

如果您真的希望将这两个行动结合起来,那么集成测试可能是更好的方法。

答案 1 :(得分:0)

嗯,你没有展示综合考试,你也没有表现出什么样的失败,所以它几乎在黑暗中工作但是要结合那些测试,我可能会做类似的事情

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的网页实际内容

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

答案 2 :(得分:0)

如果您有很多地方可以区分“相同站点”和“不同站点”行为(或任何其他双层行为),那么向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