⚖️

【RSpec】shared_examples_forとshared_contextでテストコードのリファクタリング

2023/12/01に公開

はじめに

同じテストを何回も書く必要がある時は、shared_examples_forshared_context が役に立ちます。これらは共通するテストコードをまとめ、テストの可読性や保守性を向上させる仕組みです。

今回は、shared_examples_for と shared_contextの違いや使い方についてまとめます。

本記事は Qiita のアドベントカレンダーに寄稿するために書きました。
🎄 Ruby on Rails Advent Calendar 2023

shared_examples_for と shared_context の違い

  • shared_examples_for は、共通するテストをまとめるための仕組み
  • shared_context は、共通する前提条件をまとめるための仕組み

正しい使い分け方と組み合わせを覚えれば、今後書くテストをより良くできます。

shared_examples_for の使い方

shared_examples ファイル や helper ファイルなどを作成したりして、共通するテストを書きます。

この例では、APIの各エンドポイントで必要な認証ステップを shared_examples_for ブロックにまとめています。

spec/support/shared_examples.rb
shared_examples_for 'requires authentication' do
  it 'returns unauthorized without proper authentication' do
    # 認証がない場合のテストロジック
  end

  it 'allows access with valid authentication' do
    # 認証がある場合のテストロジック
  end
end

shared_examples_for を呼び出すには、該当のテストケースで it_behaves_like メソッドを使用します。

RSpec.describe 'Some API endpoint' do
  it_behaves_like "requires authentication"
  ...
end

shared_context の使い方

同様に shared_context ファイル や helper ファイルなどを作成したりして、共通する前提条件を書きます。

前提条件とは、before句 や letsubject のことです。

spec/support/shared_context.rb
shared_context 'with valid authentication' do
  before do
    # 有効な認証のセットアップ
  end

  let(:user) { create(:user) } # FactoryBotを使用してユーザーを生成
  subject { described_class.new(user) } # インスタンスを生成するためのsubject

  # その他のセットアップや設定
end

shared_context を呼び出すのも、該当のテストケースで it_behaves_like メソッドを使用します。

describe 'Some API endpoint' do
  it_behaves_like 'with valid authentication'

  it 'performs a task with valid authentication' do
    # 有効な認証が設定された状態でのテストロジック
  end
end

shared_examples_for と shared_context の呼び出し方

rspec-coreの公式ドキュメントによると、呼び出し方は複数個あるようでした。

  include_examples "name"      # include the examples in the current context
  it_behaves_like "name"       # include the examples in a nested context
  it_should_behave_like "name" # include the examples in a nested context
  matching metadata            # include the examples in the current context

基本的には、it_behaves_likeを使用すれば問題ないようです。

参考文献 & 関連リンク

https://qiita.com/shinoharat/items/0a481bc33d9a5e81012e
https://rspec.info/features/3-12/rspec-core/example-groups/shared-examples/
https://qiita.com/advent-calendar/2023/ruby-on-rails

Discussion