次の仕様があると仮定します。
...
describe Thing do
it 'can read data' do
@data = get_data_from_file # [ '42', '36' ]
expect(@data.count).to eq 2
end
it 'can process data' do
expect(@data[0].to_i).to eq 42 # Fails because @data is nil
end
end
...
私が望んだのは、与えられたdescribeまたはcontextで変数を共有することです。ある例では値を書き、別の例ではそれを読みます。それ、どうやったら出来るの?
before(:each)
またはbefore(:all)
ブロックを使用する必要があります。
describe Thing do
before(:each) do
@data = get_data_from_file # [ '42', '36' ]
end
it 'can read data' do
expect(@data.count).to eq 2
end
it 'can process data' do
expect(@data[0].to_i).to eq 42
end
end
違いは、_before(:each)
は各ケースに対して個別に実行され、_before(:all)
はこのdescribe/context
のすべての例の前に1回実行されることです。 before(:each)
よりもbefore(:all)
を好むことをお勧めします。この場合、各例は分離されるため、良い習慣です。
get_data_from_file
の実行時間が長い場合など、before(:all)
を使用したい場合はまれです。この場合、もちろん速度を優先してテストの分離を犠牲にすることができます。ただし、before(:all)
を使用する場合、1つのテスト(it
ブロック)で@data
変数を変更すると、describe/context
スコープ内の他のテストに予期しない結果が生じることに注意してください。それ。
before(:all)
の例:
describe MyClass do
before(:all) do
@a = []
end
it { @a << 1; p @a }
it { @a << 2; p @a }
it { @a << 3; p @a }
end
出力されます:
[1]
[1, 2]
[1, 2, 3]
[〜#〜] updated [〜#〜]
あなたの質問に答えるために
describe MyClass do
before(:all) do
@a = []
end
it { @a = [1]; p @a }
it { p @a }
end
出力します
[1]
[]
最初のit
では、インスタンス変数@aをローカルに割り当てているため、before(:all)
ブロックの@aと同じではなく、他のit
ブロックからは見えません。 、object_id
sを出力することで確認できます。そのため、変更のみがトリックを行い、割り当てにより新しいオブジェクトが作成されます。
したがって、変数を複数回割り当てている場合は、おそらく1つのit
ブロックとその中に複数の期待値があるはずです。 ベストプラクティスによると、許容範囲内です
これは実際に RSpec let helper の目的であり、コードでこれを行うことができます。
...
describe Thing do
let(:data) { get_data_from_file }
it 'can read data' do
expect(data.count).to eq 2
end
it 'can process data' do
expect(data[0].to_i).to eq 42
end
end
...
私はちょうどこの同じ問題に出くわしました。 factory_girl gemを使用して解決しました。
基本は次のとおりです。
ファクトリを作成します(コードスニペットは次のとおりです。
require 'factory_girl'
require 'faker' # you can use faker, if you want to use the factory to generate fake data
FactoryGirl.define do
factory :generate_data, class: MyModule::MyClass do
key 'value'
end
end
ファクトリを作成したら、次のようなモデルを作成する必要があります。
Module MyModule
class MyClass
attr_accessor :key
#you can also place methods here to call from your spec test, if you wish
# def self.test
#some test
# end
end
end
例に戻ると、次のようなことができます。
describe Thing do
before(:all) do
@data = FactoryGirl.build(:generate_data)
end
it 'can read data' do
@data.key = get_data_from_file # [ '42', '36' ]
expect(@data.key.count).to eq 2
end
it 'can process data' do
expect(@data.key[0].to_i).to eq 42 # @data will not be nil. at this point. whatever @data.key is equal to last which was set in your previous context will be what data.key is here
end
end
とにかく、他の解決策があれば幸運をお知らせします!