🧰

【RSpec】type は何ができる?便利なメソッドを紹介します

2024/11/28に公開

こんにちは!
ラブグラフエンジニアのひろです!

今日は RSpec で指定できる type メタデータについてまとめます。
type の仕組みを理解し、効率的なテスト設計に役立ててください。

type メタデータとは?

役割

  • RSpec に「このテストが何を対象にしているか」を伝えるもの。
  • Rails では、type に応じて適切なヘルパーや設定が自動で有効になります。

https://rspec.toolboxforweb.xyz/docs/rspec-rails/directory_structure

指定例

RSpec.describe User, type: :model do
  it "バリデーションを検証する" do
    expect(User.new(name: nil)).not_to be_valid
  end
end

この例では、type: :model を指定することで、 Active Record 用の便利なヘルパーメソッドが自動で利用可能になります。

type の自動推測

RSpec には「ディレクトリ構造に基づいて type を推測する機能」があります。
例えば:

  • spec/models/user_spec.rb → 自動で type: :model
  • spec/jobs/sample_job_spec.rb → 自動で type: :job

この機能は以下の設定で有効になっています:

spec/rails_helper.rb
RSpec.configure do |config|
  config.infer_spec_type_from_file_location!
end

Rails では、この設定がデフォルトで有効です。
そのため、標準的なディレクトリ構造で作っている場合は type を明示的に指定する必要はありません。

RSpec の type メタデータ一覧と使えるメソッド

type を用途ごとに整理し、利用可能なメソッドを簡単に紹介します。

type テストするもの 説明
type: :model モデル(ActiveRecordなど) モデルのバリデーションやメソッド、スコープをテストする
type: :controller コントローラ コントローラのアクションやレスポンスをテストする
type: :request リクエスト エンドポイント全体の動作やレスポンスをテストする
type: :feature 機能(統合テスト) Capybara を使用したE2Eテスト(UIの動作)をおこなう
type: :system システムテスト ブラウザを用いた統合テスト(Capybara)
type: :job ジョブ(ActiveJob) ジョブのエンキューや実行のテストをおこなう
type: :mailer メーラー(ActionMailer) メールの送信や内容をテストする
type: :channel チャネル(ActionCable) WebSocket や ActionCable の動作をテストする
type: :view ビュー ERB/HTML のテンプレートのレンダリング結果をテストする
type: :helper ヘルパー ビューヘルパーのメソッドをテストする

type: :model

  • 概要: モデル(Active Record)のバリデーション、メソッド、スコープをテストする。

  • 主に使えるメソッド/マッチャ:

    • be_valid: モデルが有効かどうかを検証
  • サンプルコード:

RSpec.describe User, type: :model do
  it "name が必須である" do
    expect(User.new(name: nil)).not_to be_valid
  end
end

type: :request

  • 概要: リクエスト全体を通した動作をテストする。

  • 主に使えるメソッド/マッチャ:

    • get, post, put, delete: HTTPリクエストを送信
    • response: レスポンスオブジェクトを取得
    • have_http_status: レスポンスのHTTPステータスを検証
  • サンプルコード:

RSpec.describe "Users API", type: :request do
  it "ユーザー一覧を取得する" do
    get "/users"
    expect(response).to have_http_status(:ok)
  end
end

type: :job

  • 概要: Active Jobを使った非同期処理のテスト。

  • 主に使えるメソッド/マッチャ:

    • have_enqueued_job: ジョブがキューに追加されたかを検証
    • perform_now: ジョブを即時実行
    • perform_later: ジョブを非同期で実行(キューイング)
  • サンプルコード:

RSpec.describe MyJob, type: :job do
  it "ジョブがキューに追加される" do
    expect { MyJob.perform_later("arg") }.to have_enqueued_job(MyJob)
  end

  it "ジョブを同期実行できる" do
    expect { MyJob.perform_now("arg") }.not_to raise_error
  end
end

type: :mailer

  • 概要: メーラー(Action Mailer)の送信や内容をテストする。

  • 主に使えるメソッド/マッチャ:

    • deliver_now, deliver_later: メールを送信
    • have_enqueued_mail: メールがキューに入っていることを検証
    • have_body_text: メール本文に特定の文字列が含まれるかを検証
  • サンプルコード:

RSpec.describe UserMailer, type: :mailer do
  it "ウェルカムメールが送信される" do
    email = UserMailer.welcome_email(user).deliver_now

    expect(email.subject).to eq("ようこそ!")
    expect(email.to).to eq([user.email])
    expect(email.body).to have_body_text("ご登録ありがとうございます!")
  end
end

まとめ

RSpec の type は、テストの実装を補助する仕組みです。
適切に設定することで便利なヘルパーメソッドが使えるようになります。

標準的なディレクトリ構造を守っている限り type を明示する必要はありませんが、カスタムディレクトリを使用している場合は type を指定する必要があることを覚えておきましょう。

ラブグラフのエンジニアブログ

Discussion