テンプレート側
テストデータに連番をつける。(シーケンス)
通常は、FactoryBot.createやFactoryBot.buildを複数回実行した場合は常に同じデータができますが、下記のようにsequenceを使うことで複数回データを作成した際に連番データを作成することが可能です。
1 2 3 4 5 |
FactoryBot.define do factory :モデルクラス名 do sequence(:カラム名) { |n| "ここに#{n}連番を挿入" } end end |
絶対に複数データを使うとわかっているカラム等に関しては上記の機能を使用するとRspecの記述もすっきりすると思います。
モデル同士を関連づけてデータを生成する。
下記のように記述するとFactoryBot.createを実行すると同時に所属するモデルまで自動で生成してくれます。いちいちテストコード側で関連するモデルの生成処理を記述しなくてよくなります。
1 2 3 4 5 |
FactoryBot.define do factory :モデルクラス名 do association :本モデルが所属するモデル名 end end |
別名をつける。
モデル側(app/models/モデル名.rb)でモデルを別名で参照するようなソースになっていた場合は下記のように記述してモデルの仕様に合わせる必要があります。
1 2 3 4 |
FactoryBot.define do factory :user, aliases: [:別名] do end end |
複数ファクトリを作る。
下記のように記述すればファクトリを複数作成してテストコード内で使用することが可能です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
FactoryBot.define do factory :ファクトリ名 do 属性1: 属性値1 属性2: 属性値2 end factory :ファクトリ1,class: クラスのインスタンス名(User等) do 属性1: 属性値1 属性2: 属性値2 end factory :ファクトリ2,class: クラスのインスタンス名(User等) do 属性1: 属性値1 属性2: 属性値2 end factory :ファクトリ3,class: クラスのインスタンス名(User等) do 属性1: 属性値1 属性2: 属性値2 end end |
テンプレートの重複を排除する。
継承による重複排除
テンプレート側の記述方法
上のコードだとFactoryBotの記述がかなり冗長になっていますが、下記のように記述すればすっきり記述できます。構造から使うクラスがわかるためclass指定も必要なくなります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
FactoryBot.define do factory :親ファクトリ名 do 属性1: 属性値1(子ファクトリにも継承される) 属性2: 属性値2(子ファクトリにも継承される) factory :子ファクトリ1 do 属性2': 属性値2'(オーバーライド) end factory :子ファクトリ2 do 属性2': 属性値2'(オーバーライド) end factory :子ファクトリ3 do 属性2': 属性値2'(オーバーライド) end end end |
テストコード側の記述方法
1 |
FactoryBot.create(:子ファクトリ1) |
トレイト(trait)を使った重複排除
テンプレート側の記述方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
FactoryBot.define do factory :親ファクトリ名 do 属性1: 属性値1(子ファクトリにも継承される) 属性2: 属性値2(子ファクトリにも継承される) trait :子ファクトリ1 do 属性2': 属性値2'(オーバーライド) end trait :子ファクトリ2 do 属性2': 属性値2'(オーバーライド) end trait :子ファクトリ3 do 属性2': 属性値2'(オーバーライド) end end end |
テストコード側の記述方法
テストコード側の記述が継承を使用する場合に比べて少し変わります。
1 |
FactoryBot.create(:モデル名,:子ファクトリ1) |
継承とトレイトの違い
- トレイト同士を組み合わせて複雑なオブジェクトを構築できる点(継承ではできない)
コールバック
FactoryBotでcreate、build、stubする前やした後に追加のアクションを実行することができる機能です。
メリット
- 適切にコールバックを使うことによって複雑なテストシナリオも簡単にセットアップすることが可能になる。
- モデルが入れ子になっており他のモデルの属性を持っている場合とかのデータ作成に使えます。
例
下記のように記述すればFactoryBot.createを実行した後に処理内容を実行してくれます。
1 |
after(:create等のテストコード側のメソッド) { 処理内容(例:create_list等で複数インスタンスを作る等)} |
注意点
コールバックで関連するデータを準備する場合はFactoryBot.createよりはFactoryBot.buildを使った方が良い。データベースに挿入する回数が減ってパフォーマンスが上がります。
Rspec(テストコード側)
FactoryBot.create
新しいデータを作成する。(DBに保存されます。)
用途
Rspecではデータベースに保存されるので保存されたデータを活用して重複登録チェックとかをしたい場合に活用したりします。
例
1 2 3 4 |
#下記例は重複エラーになる。 FactoryBot.create(:user, email:"test@example.com") user = FactoryBot.build(:user, email:"test@example.com") user.valid? |
FactoryBot.build
新しいデータをインスタンス化する。(DBに保存はされません。)
用途
Rspecでは一時的にローカル変数に保存してデータを活用したい等の目的で使用したりします。
例
1 2 3 |
#userオブジェクトの有効性(不正な値でインスタンスが作成されていないか)をチェックする。 user = FactoryBot.build(:user) user.valid? |
FactoryBot.attributes_for(設定値)
例
1 2 |
params = FactoryBot.attributes_for(:モデルのファクトリ) post :create, params: { モデル名: params } |
この記事へのコメントはありません。