以前、factory_botの traitを使ったことがありました。
Rails + factory_botで、sub factoryやtrait・callbackを使って関連データを生成してみた - メモ的な思考的な
そんな中、 rspec-parameterized を使ってテストを書くときに、動的に trait を指定してデータを生成したくなりました。
そこで、実現できるかどうか試してみたときのメモを残します。
目次
環境
なお、今回使うfactoryはこんな感じです。
デフォルトでは name に 日本 が入りますが、 trait によりその値を変更できます。
FactoryBot.define do factory :area do name { '日本' } trait :tokyo do name { '東京都' } end trait :okinawa do name { '沖縄県' } end end end
traitを使わない場合
trait を使わない場合は、 factory_botで定義されたデフォルト値が使われます。
context 'without trait' do let!(:static_area) { create(:area) } it 'static trait' do expect(static_area.name).to eq('日本') end end
traitを静的に使ってデータを生成
trait を静的に使う場合は、 trait の値でデフォルト値が上書きされます。
RSpec.describe Area, type: :model do describe 'rspec-parameterized' do describe 'overwrite trait' do context 'static trait' do let!(:static_area) { create(:area, :tokyo) } it 'static trait' do expect(static_area.name).to eq('東京都') end end end end end
rspec-parameterized + traitを動的に使ってデータを生成
続いて、 rspec-parameterized と組み合わせることで、パラメタライズドテストの中で動的に trait を指定する方法を試してみます。
実現するには
- 事前に、
trait用シンボルを入れる変数をletで定義しておく rspec-parameterizedにて、シンボルを入れる変数に、traitとして使えるシンボルを渡すtraitを使いたくない場合は、nilを渡す
とすれば良さそうでした。
以下のテストコードもパスします。
context 'dynamic trait with rspec-parameterized' do let(:trait_symbol) { nil } let!(:dynamic_area) { create(:area, trait_symbol) } where(:trait_symbol, :result) do [ [:tokyo, '東京都'], [:okinawa, '沖縄県'], [nil, '日本'], # traitを使いたくない場合は nil を渡す ] end with_them do it 'dynamic trait' do expect(dynamic_area.name).to eq(result) end end end
ソースコード
Githubに上げました。
https://github.com/thinkAmi-sandbox/rails_7_0_minimal_app
今回のプルリクはこちら。
https://github.com/thinkAmi-sandbox/rails_7_0_minimal_app/pull/15