2016-09-21 16 views
5

rspecを使用して妥当性をテストする結果セットを返すプロセスがあります。プロセスはパラメータに基づいて異なる結果を返しますが、すべてに共通する例がたくさんありますので、それらのすべてに対して実行できる共通の例を作成したいと思います。rspec共有サンプルにパラメータを渡す

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

ので、代わりに私が前に結果を構築しています(すべて)のブロックと、このような属性の何かに割り当てる:

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 

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

答えて

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つのアサーション」のガイドラインに反するんが、操作は非常に高価であるならば、私はそれが合理的なアプローチだと思います。 :aggregate_failuresを使用すると、アサーションごとに別々の障害が発生するため、そのアサーションを逃すことはありません。

+0

これは私が望んでいたものではありませんが、これまでのところ最高の答えです。 –

0

letを使用できます。

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

これにより、後でテストで使用できるインスタンス変数が作成されます。 let上のドキュメントへ

アコード、

あなたの代わりに、インスタンス変数を作成 にブロックする前に使用する変数を割り当てる必要が

、聞かせて使用します。使用して変数を遅延させる は、テストで初めて使用されたときにのみロードされ、特定のテストが終了するまでキャッシュされます( )。

BAD

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 

GOOD

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

letを使用する際の問題は、この例の間だけキャッシュされることです。私がテストで10 "it"を持っていればlet変数の値を10回計算するつもりです。私の場合は、各「それ」ではなく、文脈全体に対して一度結果を構築することが不可欠です。それ以外の場合は、私のユニットテストは1日以上実行され、誰もそれを使用しません。 –

12

あなたはこのように共有例に引数を渡すことができます。

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

そして、このようなmy_argumentに渡す:

あなたは、単一の例にグループ結果のすべてのあなたの主張をできた
it_behaves_like "A result", my_argument 
+2

これが受け入れられる回答である必要があります。 – mikias

関連する問題