5

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

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.)。我真的不明白为什么?第二个“获取”调用可能无法正确重置某些内容。我寻找“重置”请求的方法但没有成功。

相关:在 Rails 集成规范中向同一个控制器发出两个请求

4

3 回答 3

11

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

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 文档

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

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

于 2013-05-08T14:33:36.740 回答
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 在浏览器中查看测试失败时网页中的实际内容

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

于 2012-12-12T04:18:34.043 回答
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
于 2015-06-27T14:42:13.833 回答