18
24

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

RSpecにおけるFactoryGirlまとめ

Last updated at Posted at 2017-07-20

はじめに

FactoryGirlを使って簡単なモックオブジェクトは作れるが、associationやらtraitやらsequenceやら便利な機能をいちいち調べるのめんどくさいので、今のうちにまとめておく。

FactoryGirlインストール

Gemfile
group :test do
  gem 'rspec-rails'
  gem 'factory_girl_rails'
end

version指定しないと最新版がインストールされるので、
version指定する場合は、

Gemfile
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

ちなみに、作成されたファクトリーの中身は、こんな感じ。

spec/factories/user.rb
FactoryGirl.define do
  factory :user do
    name "MyString"
  end
end

ここにテストデータを書いていきます。

FactoryGirlの定義

spec/factories/user.rb
FactoryGirl.define do
  factory :user do
    name "hoge"
  end
end

RSpec実行コマンド

spec/models/user_spec.rb
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の部分は省略できます。

spec/rails_helper.rb
RSpec.configure do |config|
  ...
  config.include FactoryGirl::Syntax::Methods
  
  #config.fixture_path = "#{::Rails.root}/spec/fixtures"
  ...
end  

と記述すれば、省略できます。またfixtureを使用しないのであればコメントアウトしてしましましょう!

spec/models/user_spec.rb
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

共通部分は最初のブロック内で記述して、変更したい部分はネストさせて使い分けるやり方もある

spec/factories/user.rb
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の機能を使うと、同じ名前で複数のバリエーションを用意することができる。
特定のカラムだけを変更できる。
複数カラム変更する場合は、楽だし可読性も上がる

spec/factories/user.rb
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を第二引数で指定する

spec/models/user_spec.rb
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

spec/factories/post.rb
FactoryGirl.define do
  factory :post do
    sequence(:title){ |n| "test_#{n}" }
    association :user
  end
end
spec/factories/user.rb
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

18
24
0

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
24

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?