1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Rails】RSpecのletとlet!の違い

Posted at

はじめに

こんにちは。アメリカ在住で独学エンジニアを目指している Taira です。

RSpec でテストを書くときによく出てくるletlet!
どちらもテストで使う変数を定義するためのヘルパーですが、動き方が少し違います。

この記事では、それぞれの特徴と使い分け方を、コード例を交えて解説します。


1. letとは?

letは**遅延評価(lazy evaluation)**される変数を定義します。
つまり、初めて呼び出されたときに実行されるという動きです。

RSpec.describe User do
  let(:user) { User.create(name: "Taro") }

  it "最初に呼び出したタイミングで実行される" do
    # この時点ではUserはまだ作られていない
    expect(User.count).to eq(0)

    user # ← 初めて呼び出したタイミングでUserが作成される
    expect(User.count).to eq(1)
  end
end

ポイント

  • 実際に使われなければ、定義部分は実行されない
  • 無駄なデータ作成を避けられる(テスト高速化につながる)

2. let!とは?

let!は**即時評価(eager evaluation)**されます。
テストが始まる前に必ず実行されるため、呼び出さなくても変数が作られます。

RSpec.describe User do
  let!(:user) { User.create(name: "Taro") }

  it "テスト開始前にすでに作成されている" do
    # let! は呼び出さなくても事前に実行される
    expect(User.count).to eq(1)
  end
end

ポイント

  • 呼び出さなくても必ず実行される
  • 事前にデータを用意しておきたいときに便利

3. 違いをまとめると

特徴 let let!
実行タイミング 初回呼び出し時 各テストの実行前
呼び出さない場合 実行されない 必ず実行される
主な用途 必要なときだけデータを用意 前提条件として必ずデータを用意

4. 使い分けの目安

letを使うべきとき

  • 不要なデータ作成を避けたいとき
  • テストの中で呼ばれるかわからないが、とりあえず変数を用意しておきたいとき
let(:article) { create(:article) } # 呼ばれない限りDBにINSERTされない

let!を使うべきとき

  • テスト開始前に必ずデータが必要なとき
  • beforeブロックでセットアップする代わりに使うとスッキリする場合
let!(:article) { create(:article) } # 各itの前に必ず作られる

5. 実務でよくあるハマりポイント

❌「あれ、データがない…」

let(:user) { create(:user) }

it "ユーザー数を確認する" do
  expect(User.count).to eq(1) # ← 0になる(userを呼び出してない)
end

解決策:必ず事前に必要ならlet!にするか、userを呼び出す。


6. まとめ

  • let → 初回呼び出し時に実行(遅延評価)
  • let! → テスト開始前に実行(即時評価)
  • パフォーマンスを意識してletを使い、**必須データはlet!**で作成する

💡 基本はlet、本当に必要なときだけlet!にするとテストが速く、意図しないデータ作成も防げます。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?