5

同じテストでいくつかのgetリクエストをグループ化したいのですが、動作が不安定になります。次の2つのテストがあります。

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

これを1つのテストで組み合わせたいのですが、そうすると、2番目のアサートが誤って失敗します(「table#order_requeststr#order_request_1000244799」に一致する要素が正確に0であると予想され、1が見つかりました)。理由がよくわかりませんか?2番目の「get」呼び出しで何かが正しくリセットされない可能性があります。リクエストを「リセット」して成功しない方法を探しました。

関連:Rails統合仕様で同じコントローラーに2つのリクエストを行う

4

3 に答える 3

11

(統合ではなく)機能テストで気付いた重要な違いの1つは、コントローラーの状態が要求間でリセットされていないように見えることです。これにより、予期しない結果が生じる可能性があります。たとえば、次の(考案された)コントローラーについて考えてみます。

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

  def two 
    render :nothing => true
  end 
end

アクション「1」は@thingyを設定しますが、アクション「2」は設定しません。ただし、この機能テストは失敗します。

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が、テストメソッドの期間中、コントローラーにインスタンス変数として残っているためです。

1つのテスト内で複数のget/put / etc呼び出しを行うことは確かに可能ですが、テストメソッドごとに複数のアクションをテストするようには設計されていないと思います。Rails API TestCaseドキュメントによると:

機能テストでは、テスト方法ごとに1つのコントローラーアクションをテストできます。これを統合テスト(ActionDispatch :: IntegrationTestを参照)と混同しないでください。統合テストは、複数のコントローラーと複数のアクション(つまり、複数の異なるHTTPリクエスト)を含む可能性のある「ストーリー」に似ています。

2つのアクションを本当に組み合わせたい場合は、統合テストの方が適している可能性があります。

于 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を使用してテストが失敗した時点で実際にWebページに何があるかを確認します。

複合テストと個別テストの違いは、データベースが各テスト間でクリアされるため、最初の販売者は複合テストのデータベースに引き続き存在しますが、個別テストとして実行された場合は2番目のテストには存在しません。

于 2012-12-12T04:18:34.043 に答える
0

「同じサイト」と「異なるサイト」の動作(または他の2層の動作)を区別する場所がたくさんある場合は、2つのテストを追加するだけのヘルパーメソッドを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 に答える