##let
とlet!
の違い
let
は遅延評価と呼ばれ、テスト内でメソッドを使用した時に初めて評価(定義)され、
let!
はテストが実行される前(it内のテストが実行される前)に評価(定義)される。
■let
describe 'letの挙動を確認' do
let(:user) { build(:user) }
it 'userインスタンスが有効であること' do
expect(user).to be_valid
※↑ここではじめて読み込まれる
end
end
上記のようにlet
は呼び出された時に、はじめてデータを読み込むので無駄にデータベースに問い合わせてしまってテストが遅くなるといったことを予防してくれる。
■let!
describe 'let!の挙動を確認' do
let(:user) { create(:user) }
let!(:user_task) { create(:task, user_id: user.id, title: 'test_title') }
it 'userがtaskを持っていること' do
expect(user.tasks.first.title).to eq 'test_title'
end
end
task
インスタンスの入った変数「user_task」が作成されたのち、expect内のテストが実行される。
##beforeとの違い
let
とlet!
以外によく聞くのはbefore
だが、before
はlet!
と挙動がさほど変わらないと言っていい。
let!
と主な違う点は、インスタンス変数の定義以外にも使用できることである。
describe 'beforeの挙動を確認' do
let(:user) { create(:user) }
before { login(user) } #loginメソッドを定義している前提
it 'is success to edit user' do
visit edit_user_path(user)
fill_in "Email", with: "edit_user@example.com"
click_button "Update"
expect(page).to have_content 'User was successfully updated.'
expect(current_path).to eq user_path(user)
end
end
例えば、ログイン後の動作をテストしたい場合、このテストコードの内容を見ると、既にログインをすましていて、ユーザープロフィールなどを更新できるかのテストを行っている。
この**「既にログインを済ます」**箇所がbefore
にあたる。
またlet!
とbefore
の実行順序は定義した順番で実行される。
##let
/let!
/ before
の使い分け
let
:テストで何回か使うインスタンス変数がある時
let!
:テストのブロック内で毎回使うインスタンス変数がある時
before
:テストのブロック内で毎回適用させたいメソッドなど(インスタンス変数以外)がある時