はじめに
FactoryGirlを使って簡単なモックオブジェクトは作れるが、associationやらtraitやらsequenceやら便利な機能をいちいち調べるのめんどくさいので、今のうちにまとめておく。
FactoryGirlインストール
group :test do
gem 'rspec-rails'
gem 'factory_girl_rails'
end
version指定しないと最新版がインストールされるので、
version指定する場合は、
group :test do
gem 'rspec-rails'
gem 'factory_girl_rails', '~> 4.0'
end
んで、 bundle install
して完了
FactoryGirlのファイル生成
基本的にFactoryGrilをインストールした状態で、モデルを作成するとモデルと一緒にファクトリーも生成される。
$ rails g model User name:string
Running via Spring preloader in process 39201
invoke active_record
create db/migrate/20170720132710_create_users.rb
create app/models/user.rb
invoke rspec
create spec/models/user_spec.rb
invoke factory_girl
create spec/factories/users.rb
ちなみに、作成されたファクトリーの中身は、こんな感じ。
FactoryGirl.define do
factory :user do
name "MyString"
end
end
ここにテストデータを書いていきます。
FactoryGirlの定義
FactoryGirl.define do
factory :user do
name "hoge"
end
end
RSpec実行コマンド
require 'rails_helper'
RSpec.describe User, type: :model do
describe "User" do
context "user.nameが生成されるテスト" do
it "user.nameがhogeである" do
user_name = FactoryGirl.create(:user).name
expect(user_name).to eq "hoge"
end
end
end
end
FactoryGirlの設定
FactoryGirlを生成するときに、
FactoryGirl.create(:user)
と書きますが、FactoryGirl
の部分は省略できます。
RSpec.configure do |config|
...
config.include FactoryGirl::Syntax::Methods
#config.fixture_path = "#{::Rails.root}/spec/fixtures"
...
end
と記述すれば、省略できます。またfixtureを使用しないのであればコメントアウトしてしましましょう!
require 'rails_helper'
RSpec.describe User, type: :model do
describe "User" do
context "user.nameが生成されるテスト" do
it "user.nameがhogeである" do
user_name = create(:user).name
expect(user_name).to eq "hoge"
end
end
end
end
FactoryGirlの呼び出し
build
buildしたオブジェクトを生成(DB保存なし)
FactoryGirl.build(:user)
create
createしたオブジェクトを生成(DB保存する)
FactoryGirl.create(:user)
attributes_for
hashを生成する
FactoryGirl.attributes_for(:user)
ネストしたFactoryGirl
共通部分は最初のブロック内で記述して、変更したい部分はネストさせて使い分けるやり方もある
FactoryGirl.define do
factory :user do
available true
factory :user_for_validation do
name "hoge"
...
end
factory :user_for_method do
name "fuga"
...
end
end
end
traitでカラムを変更
traitの機能を使うと、同じ名前で複数のバリエーションを用意することができる。
特定のカラムだけを変更できる。
複数カラム変更する場合は、楽だし可読性も上がる
FactoryGirl.define do
factory :user do
name "hoge"
trait :age_under_20 do
age 18
...
end
trait :age_over_20 do
age 35
...
end
end
end
FactoryGirlでオブジェクトを生成するとき、traitを第二引数で指定する
require 'rails_helper'
RSpec.describe User, type: :model do
describe "User" do
context "user.nameが生成されるテスト" do
it "user.nameがhogeである" do
user_age = FactoryGirl.create(:user, :age_under_20).age
expect(user_age).to eq 18
end
end
end
end
FactoryGirlでアソシエーションを定義
アソシエーションのテスト時には、関連を定義する必要がある。
# app/models/user.rb
class User < ActiveRecord::Base
has_many :posts
...
end
# app/models/post.rb
class Favorite < ActiveRecord::Base
belongs_to :user
...
end
FactoryGirl.define do
factory :post do
sequence(:title){ |n| "test_#{n}" }
association :user
end
end
FactoryGirl.define do
factory :post do
title "test"
after(:create) do |user, evaluator|
create_list(:post, 5, user: user)
end
end
end
これで、create(:user)
した時に、has_manyのpostオブジェクトも生成される。。はず。。
補足
sequence
自動採番してくれる
作成した順番でnにインクリメントした番号が入る
create_list
指定した第二引数の数分だけオブジェクトを作成
第三引数は、belongs_toで紐づいているオブジェクトを指定
evaluator
ブロック変数のevaluatorは全てのオブジェクトが格納される
after部分について
trait化することも可能。
検証しきれてません...
終わりに
ここら辺を覚えれば、初心者から初級者に繰り上げできると思います。
まずは公式ドキュメント!
殴り書きすぎたので、平日の夜にqiitaアップするもんじゃないな~と思いました。。。
参考url
factory_girl/GETTING_STARTED.md at master · thoughtbot/factory_girl
RailsでFactoryGirlを使ってみるメモ [俺の備忘録]
いまさら聞けないfactory_girl入門 - Grooves開発ブログ
RSpecにおけるFactoryGirlの使い方まとめ - Qiita
【解決済み】FactoryGirl の relation の定義の仕方がよくわからない>< - yoshiori.github.io