こんにちは、プレイライフの熊崎です。
最近野菜をとれていなかったので、この土日はいっぱい野菜を食べたいと思います。
本日3本目はletとbeforeの使い分けについてアウトプットしていきます。
let
メモ化されたヘルパーメソッドを定義する。同じexampleの中ではキャッシュされるが、異なるexample間ではキャッシュされない。
遅延評価される。letが定義するメソッドが最初に呼び出されるまで評価されない。
let(:user) { User.create(name: "田中太郎") }
# letは遅延評価されるため、userが呼び出されるまで、Userにはレコードが作られていない状態になる。そのためテストが通らない。
it 'ユーザーが取得できること' do
expect(User.find_by(name: "田中太郎")).to eq user
end
let!
各exampleの実行前に、定義されたメソッドを呼び出すことができる。
let!(:user) { User.create(name: "田中太郎") }
# let!にすることで、以下のテストケースの前に、userメソッドが呼ばれるため、Userにレコードが存在する状態になる。そのため、テストには通る。
it 'ユーザーが取得できること' do
expect(User.find_by(name: "田中太郎")).to eq user
end
before
テストケースの前に、行いたい処理をブロック内に書くことで、テストケースが実行される前にブロック内の処理が行われるようにする。
before do
User.create(name: "田中太郎")
end
# この場合はuserがテストコードにないので、let(:user)を使用する必要がない。
it 'ユーザーが取得できること' do
expect(User.count).to eq 1
end
それぞれの使い分け
先ほどまでの実例から、以下のように使い分けるのが適切だと感じた。
let:テストコード内に、定義したヘルパーメソッドが存在する場合
let!:テストコード内に、定義したヘルパーメソッドが存在し、かつテストの実行前にヘルパーメソッドを実行したい場合
before:テストコード内でヘルパーメソッドを定義する必要がない場合
最後に
それぞれの挙動を理解していないと、テストコードに存在しないヘルパーメソッドをletで用意している。といった状況になり、レビュワーや数ヶ月後の自分が混乱するので使い分けを徹底していく必要があると感じた。
参考記事