以前、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