LoginSignup
18
7

More than 5 years have passed since last update.

FactoryBotでfixtureのデータを変更する方法

Last updated at Posted at 2018-10-30

はじめに

FactoryBotを使うにあたって、既に存在するファクトリーで定義されているものと違うファクトリーで試したい、または一部変更してテストしたい場面があった。
その際にいくつかやり方があったので残しておく。

環境

Ruby 2.5.1
Rails 5.1.6
Rspec 3.8
factory_bot_rails 4.11.1

前提

  • Userモデルのモデルスペックを書いている
  • 既に以下のファクトリーが作成済みで他のメソッドのテストで使用されている
spec/factories/user.rb
  factory :user, class: 'User' do
    id { '1' }
    gender { nil }
    last_name { '鞘師' }
    first_name { '里保' }
    last_name_yomi { 'sayashi' }
    first_name_yomi { 'riho' }
    email { '' }
    phone_number { nil }
  end
  • テストを追加するにあたって作成済みのファクトリーの属性の値を変更したい
    • 例) genderをfemale male に設定したい
    • 例) birth_atというモデルで定義されている属性を追加したい
    • 例) 属性の値がまるまる違うuser2を用意したい

attributeの値を変更してテストを実行する方法3つ

上記で挙げたような要望を叶えるには主に3つやり方がある。

classを指定して新たなファクトリーを作成

まずは例で3つめに挙げたまるまる新たにファクトリーを作成する方法
この方法を取る場合は、既にあるファクトリーが書かれているファイルに追記する形になる。
この際大事なのが、対象のクラスを明記すること。通常モデル名を指定するところを自作の名前に変えているので、どのクラスでnewしてあげるべきなのかを明示しないとuninitialize constant User2 というエラーが出る。

spec/factories/user.rb
  factory :user2, class: 'User' do
    id { '2' }
    gender { 'male' }
    last_name { '勇気' }
    first_name { '須藤' }
    last_name_yomi { 'sudo' }
    first_name_yomi { 'yuki' }
    birth_at { Date.new(2000, 11, 12) }
    email { 'hoge@sample.com' }
    phone_number { '0X011112222' }
  end

ファクトリー側は準備ができたので、spec側の設定をする。
RSpec上で使う変数名とbuild(またはcreate)するファクトリーの名前は一致してなくても大丈夫。

spec/models/smarthr_crew_spec.rb
let(:user) { build(:user2) }

traitを使う

次に、属性定義の一部変更を纏めたい場合に使えるのがtrait
こちらはまるまる新たにファクトリーを作成しないので、ファクトリーのファイルがスッキリするし、テストでも使いやすい。

:userをbuildした後にuserをブロックで回して属性に値を指定できる。
複数の属性でもまとめられる。

spec/factories/user.rb
  trait :male do
    after(:build) do |user|
      user.gender = 'male'
      user.birth_at = '1998,12,11'
    end
  end

spec側では、既に作成してあったuserに、:maleを追加でtraitを指定する。

spec/models/smarthr_crew_spec.rb
let(:user) { build(:user,:male) }

spec側で指定

一番お手軽なのがこの方法だった。
spec側だけの設定で済むので楽で、可読性も高いように感じた。
属性と値をセットで引数として渡してあげる。

spec/models/smarthr_crew_spec.rb
let(:user) { build(:user, gender: 'no_selected') }

まとめ

それぞれ合うケース合わないケースがあると思うので適宜使い分けていきたい。

18
7
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
7