LoginSignup
168
151

More than 5 years have passed since last update.

FactoryBot Traits

Last updated at Posted at 2014-02-23

FactoryBot はフィクスチャのツールです。
多くのフィクスチャを必要とするときは Traits が便利です。

Setup

Ruby on RailsRSpec のテスト環境を構築して確認しましょう。
今回はコンソールモードで確認します。spec/factories のファイルを修正するとコンソールで FactoryBot.reload を実行してください。

mkdir factory_bot_rails_example && cd factory_bot_rails_example/ && rails new . --api -BT
echo "gem 'pry-rails', group: [:development]" >> Gemfile
echo "gem 'factory_bot_rails', group: [:development, :test]" >> Gemfile
echo "gem 'rspec-rails', group: [:development, :test]" >> Gemfile
bundle
bundle exec rails generate rspec:install
rails generate model product title vendor state 
rails console

Usage

Trait

traitは項目をグループにすることができます。

FactoryBot.define do
  factory :product do
    title 'iPad'

    trait :modify do
      title 'iPhone'
    end
  end
end

フィクスチャにするにはトレイトのシンボルを第2引数に指定します。

例では、シンボルにmodifyを指定するとtitleiPadからiPhoneに変更されます。

[1] pry(main)> FactoryBot.reload
[2] pry(main)> FactoryBot.attributes_for(:product)
=> {
    :title => "iPad"
}
[3] pry(main)> FactoryBot.attributes_for(:product, :modify)
=> {
    :title => "iPhone"
}

Traits

traitstraitをまとめることができます。

trait :base do
  vendor 'Apple'
end

trait :activate do
  state :active
end

factory :product_activate, traits: [:base, :activate]

トレイトのシンボルをは引数に複数を指定できます。また、traitsは第1引数にシンボルを指定します。

例では、同じ値が出力されています。フィクスチャにラベルが付いて便利ですね。

[4] pry(main)> FactoryBot.reload
[5] pry(main)> FactoryBot.attributes_for(:product, :base, :activate)
=> {
     :title => "iPad",
    :vendor => "Apple",
     :state => :active
}
[6] pry(main)> FactoryBot.attributes_for(:product, :base, :activate)
=> {
     :title => "iPad",
    :vendor => "Apple",
     :state => :active
}

Transient

transientは内部で利用する変数ですが、traitと組合せて利用することができます。

transient do
  time true
end

trait :cancel do
  state :canceled
  canceled_at { Time.now if time }
end

factory :product_cancel, traits: [:base, :cancel]

traitのブロッブのブロックはある程度は自由なエリアです。 (夢が広がりますね。

例では、time変数でcanceled_atのセットを制御しました。

[7] pry(main)> FactoryBot.reload
[8] pry(main)> FactoryBot.attributes_for(:product_cancel)
=> {
          :title => "iPad",
         :vendor => "Apple",
          :state => :canceled,
    :canceled_at => 2018-02-22 22:22:22 +0900
}
[9] pry(main)> FactoryBot.attributes_for(:product_cancel, time: false)
=> {
          :title => "iPad",
         :vendor => "Apple",
          :state => :canceled,
    :canceled_at => nil
}

Tips

factoryの引数にはtraitsやブロック(doend)などを指定できます。
(traitsのブロックは1項目なら{}で1行で記述できます。)

factory :product_ipod_touch, traits: [:base, :activate] do
  title 'iPod touch'
end

traitsとブロックでフィクスチャをスッキリと管理することができます。 (キリッ

[10] pry(main)> FactoryBot.reload
[11] pry(main)> FactoryBot.attributes_for(:product_ipod_touch)
=> {
     :title => "iPod touch",
    :vendor => "Apple",
     :state => :active
}

Example

紹介したサンプルはこちらです。

FactoryBot.define do
  factory :product do
    title 'iPad'

    trait :modify do
      title 'iPhone'
    end

    transient do
      time true
    end

    trait :base do
      vendor 'Apple'
    end

    trait :activate do
      state :active
    end

    trait :cancel do
      state :canceled
      canceled_at { Time.now if time }
    end

    factory :product_activate, traits: [:base, :activate]
    factory :product_cancel, traits: [:base, :cancel]

    factory :product_ipod_touch, traits: [:base, :activate] do
      title 'iPod touch'
    end

    factory :product_ipod_nano,    traits: [:base, :activate] { title 'iPod nano' }
    factory :product_ipod_shuffle, traits: [:base, :activate] { title 'iPod shuffle' }
    factory :product_ipod_classic, traits: [:base, :activate] { title 'iPod classic' }
  end
end
168
151
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
168
151