すでに前回のすごいぞRSpec(shared example group編) - ぷろぐらまねがで登場してるけどあらためてletを調べるよ。rspec-core(2.5.1)/features/helper_methods/let.featureを参考に。
let
要するにメモ化するわけで、同一サンプル内だと同じオブジェクトを使いまわせるのだな。違うサンプルでは改めて評価される。さらに遅延評価なので実際に評価されるのは最初にメソッドが呼ばれたときだ。
$count = 0 describe 'let' do let(:count) { $count += 1 } it 'memoizes the value' do count.should == 1 count.should == 1 end it 'is not cached across examples' do count.should == 2 end end
% rspec -cfs let_1.rb let memoizes the value is not cached across examples Finished in 0.00127 seconds 2 examples, 0 failures
let!
letとの違いは評価のタイミング。letが遅延評価なのに対してlet!はbefore each的に各サンプルの実行前に評価される。
$count = 0 describe 'let!' do invocation_order = [] let!(:count) do invocation_order << :let! $count += 1 end it 'calls the helper method in a before hook' do invocation_order << :example invocation_order.should == [:let!, :example] count.should == 1 end end
% rspec -cfs let_2.rb let! calls the helper method in a before hook Finished in 0.00056 seconds 1 example, 0 failures
じゃあlet!とbeforeってどんな順番なのか?
気になったのでやってみた。
$count = 0 describe 'let!' do invocation_order = [] before(:each) { invocation_order << :before1 } let!(:count) do invocation_order << :let! $count += 1 end before(:each) { invocation_order << :before2 } it 'calls the helper method in a before hook in described order' do invocation_order << :example invocation_order.should == [:before1, :let!, :before2, :example] count.should == 1 end end
% rspec -cfs let_3.rb let! calls the helper method in a before hook in described order Finished in 0.00062 seconds 1 example, 0 failures
ということでbeforeと同じタイミングで上から順番に評価されるっぽい。
letを単体で使うのはあまり効果ないような気がするけどどうだろうか?shared example groupやmockと組み合わせるのが主になるのかな。
続く