web-dev-qa-db-ja.com

rspec共有サンプルにパラメーターを渡す

Rspecを使用して有効性をテストしたい結果セットを返すプロセスがあります。プロセスはパラメーターに基づいて異なる結果を返しますが、それらすべてに共通する多くの例があるため、それらすべてに対して実行できる一連の共通例を作成したいと思います。

推奨される方法は、letを使用して結果を構築することです。問題は、各プロセスが結果を生成するのに1〜2分かかり、おそらく30の例があることです。さまざまなパラメーターに基づくすべての順列で、約500の例を実行しています。各例の結果を再構築する必要がある場合、テストは1日以上実行されます。

したがって、代わりにbefore(:all)ブロックで結果を作成し、それを次のような属性に割り当てます。

RSpec.describe 'Test Description' do
  attr_reader :result

  before(:all)
    @result = build_result({some_parameters})
  end

  context 'Some context' do
    it 'Looks lik a result' do 
      expect(result.something).to ...
    end

    it 'Feels lik a result' do 
      expect(result.something).to ...
    end
  end
end

たぶん、属性を使用するよりも良い方法があるでしょう。私はこのようなことをしたいです:

RSpec.describe 'Test Description' do
  attr_reader :result

  before(:all)
    @result = build_result({some_parameters})
  end

  context 'Some context' do
    it_behaves_like "A result" result
  end
end

このコンテキストで属性を使用すると失敗します。これを行う別の方法はありますか?

16
Nth boss

結果に対するすべてのアサーションを1つの例にグループ化できます。このように、letは一度だけ評価されます。

RSpec.describe 'Test Description' do
  context 'for params x and y' do
    let(:expected_x) { 'x' }
    let(:expected_y) { 'y' }

    subject { build_result({x: 'x', y: 'y'}) }

    specify :aggregate_failures do
      expect(subject.x).to eq(expected_x)
      expect(subject.y).to eq(expected_y)
    end
  end
end

「1つのテスト、1つのアサーション」のガイドラインに反しますが、操作に非常にコストがかかる場合は、合理的なアプローチだと思います。 :aggregate_failures アサーションごとに個別のエラーが発生するため、それを見逃すことはありません。

1
Laura Paakkinen

次のように引数を共有サンプルに渡すことができます:

shared_examples_for "A result" do |argument|
 # some tests with argument
end

そして、次のようにmy_argumentを渡します。

it_behaves_like "A result", my_argument
71
Ryan Hertz

letを使用できます。

let(:result)     { build_result({some_parameters}) }

これにより、後でテストで使用できるインスタンス変数が作成されます。

let に関するドキュメントに従ってください、

Beforeブロックを使用してインスタンス変数を作成する代わりに変数を割り当てる必要がある場合は、letを使用します。 let変数を使用すると、テストで初めて使用されたときにのみ変数がロードされ、その特定のテストが完了するまでキャッシュされます。

[〜#〜]悪い[〜#〜]

describe '#type_id' do
  before { @resource = FactoryGirl.create :device }
  before { @type     = Type.find @resource.type_id }

  it 'sets the type_id field' do
    expect(@resource.type_id).to equal(@type.id)
  end
end

[〜#〜]良い[〜#〜]

describe '#type_id' do
  let(:resource) { FactoryGirl.create :device }
  let(:type)     { Type.find resource.type_id }

  it 'sets the type_id field' do
    expect(resource.type_id).to equal(type.id)
  end
end
2
davidhu

引数をshared_exampleスペックファイルに渡したい場合は、次のようなものを使用する必要があります

it_behaves_like 'SHARED_EXAMPLE_NAME', { params1: param2, param2: param2 }

ハッシュカプセル化せずにパラメーターを渡すこともできます。これは、そのパラメーターを共有ファイルにどのように使用するかによって異なります。私の場合、動的パラメーターでAPIを呼び出す必要があります。

RSpec.shared_examples 'SHARED_EXAMPLE_NAME' do |params = {}|

FYI:Factoryデータをパラメーターとしてshared_exampleスペックファイルに渡すことはできません。ファクトリをshared_exampleスペックファイルに明示的に呼び出す必要があります。

0
Touseef Murtaza