読者です 読者をやめる 読者になる 読者になる

ネオキャリアグループ開発者ブログ

ネオキャリアグループの技術者による開発ブログ

新人よう太の冒険: FactoryGirlとの出会い ~序章~

こんにちは!こんばんは!

あけましておめでとうございます!

新卒エンジニアのよう太です。


突然ですが、皆さん


『きれいなおねえさんは、好きですか。』

f:id:Yoko_Takaki:20170113210827j:plain


私は大好きです。
かわいい女の子も好きです。

と、いうことで
今回は私が大好きな『Factory Girl』について書こうと思います。

 

こちらの記事は、Qiitaに投稿したものと同じ内容になっています。

世界一やさしいFactoryGirlの使い方:入門編 - Qiita

 

FactoryGirlって誰?


FactoryGirlとは、テストデータの作成を手伝ってくれるgemです。
テストデータ...
それはテストコードを書く上で切っても切り離せない存在です。
自力でテストデータを用意することも可能ですが、
FactoryGirlを使用すると、複数のテストデータなどを簡単に作成することができます!


FactoryGirlのインストール


それでは、FactoryGirlをインストールしてみましょう。

まず、Gemfileに'factory_girl_rails'を追加してください。
今回私は新規アプリを作成したので、'rspec-rails'も一緒に追加しました。

group :development, :test do
gem 'rspec-rails',
gem 'factory_girl_rails'

 

このままbundle installを行うと、最新バージョンがインストールされるので、
バージョンを指定したい方は

'factory_girl_rails', '~> 4.0'


このように、gemの後ろに指定したいバージョンを書いてください。


 FactoryGirlと出会ってみる

 

ファクトリーファイルの作成


インストールが終わったら、早速ファクトリーをアプリケーションに追加してみましょう。
FactoryGirlをインストールしている状態でモデルを作成すると、
モデルと一緒にファクトリーも作成されます。

$ rails g model Blog title:string word:text writer:string
Running via Spring preloader in process 7449
invoke active_record
create db/migrate/2016**********_create_blogs.rb
create app/models/blog.rb
invoke rspec
create spec/models/blog_spec.rb
invoke factory_girl
create spec/factories/blogs.rb

既にアプリケーションをお持ちの方は、
specディレクトリの配下にfactoriesディレクトリを作成し、

モデル名.rb


上記のようなファイル名を作ってください。

 

デフォルトのテストデータ


ファクトリーファイルの作成ができたら、テストデータを作成してみましょう。


先ほど rails gコマンドでBlogモデルを作成したので、
spec/factories/blogs.rbで定義します。

モデルと一緒に作成されたspec/factories/blogs.rbを見てみると、
下記のようなテストデータが自動的に作成されています。

*注意 FactoryGirlをインストールする前に作成したモデルに対しては、手動で定義する必要があります。

FactoryGirl.define do
  factory :blog do
     title "MyString"
     word "MyText"
     writer "MyString"
  end
end


せっかくテストデータを用意してくれたので、
テストを実行するとどのようなデータができるのか試してみましょう。

FactoryGirlと遊んでみる


テストデータの生成

FactoryGirlの挙動を確認するために、簡単なテストコードを書いてみました。

spec/controllers/blogs.rb

require 'rails_helper'
RSpec.describe BlogsController, type: :controller do
describe '#create' do
context '正常系' do
context 'DBに登録されていないBlogのtitleである場合' do
it '新しいモデルが生成される' do
# setup
blogs_model = FactoryGirl.create(:blog)

# exercise
post :create

# verify
actual = Blog.find_by({title: blogs_model.title})
expect(actual).not_to be nil
end
end
end
end
end

*テストの対象はblogs_controllerです。

app/controllers/blogs_controller.rb

class BlogsController < ApplicationController
def create
Blog.find_or_create_by(title: "TestTitle")
end
end

 

テストコードの中に、下記のようなコードが書かれています。

spec/controllers/blogs.rb

blog_model = FactoryGirl.create(:blog)

 

このように、FactoryGirl.create(:モデル名)と記述した場合
DBにテストデータが保存されます。

試しにtest環境のDBを覗いてみると...

mysql> select * from blogs; 
+----+----------+--------+----------+---------------------+---------------------+
| id | title | word | writer | created_at | updated_at |
+----+----------+--------+----------+---------------------+---------------------+
| 1 | MyString | MyText | MyString | 2016-**-** **:**:** | 2016-**-** **:**:** |
+----+----------+--------+----------+---------------------+---------------------+

 

Blogテーブルにテストデータが保存されていることが確認できました!

 

* createの他にも、buildやattributesといったテストデータの生成方法があります。

テストデータ生成方法の例
FactoryGirl.build(:モデル名)
FactoryGirl.create(:モデル名)
FactoryGirl.attributes_for(:モデル名)

テストデータの上書き


テストコードを書いていくと、デフォルトのテストコードではなく
より現実的なデータを使用したくなるかもしれません。
そんな時は、テストデータを生成する際に、引数として「任意のテストデータ」を追加してみましょう。

Blogモデルには[writer]というブログの著者の名前を格納するカラムがあるので、
著者の名前を指定してみます。

spec/controllers/blogs.rb
blog_model = FactoryGirl.create(:blog, writer:'asopasomaso')

 

このテストコードを実行すると、

著者の名前が"asopasomaso"なテストデータが生成されます。

test環境のDBを検索してみると...

mysql> select * from blogs where writer = 'asopasomaso'; 
+----+----------+--------+-------------+---------------------+---------------------+
| id | title | word | writer | created_at | updated_at |
+----+----------+--------+-------------+---------------------+---------------------+
| 2 | MyString | MyText | asopasomaso | 2016-**-** **:**:** | 2016-**-** **:**:** |
+----+----------+--------+-------------+---------------------+---------------------+

 asopasomasoがDBに存在することが確認できました。

複数のテストデータ作成


ここまで取り上げてきたテストデータの生成方法では、
一度に1つのテストデータしか作成することができません。
複数のテストデータを生成したい場合は、create_listの引数に「生成したいテストデータの数」を追加してください。
例として、5つのBlogを作成してみます。

spec/controllers/blogs.rb

blog_model = FactoryGirl.create_list(:blog, 5)

 

このテストコードを実行して、test環境のDBを見てみます。

mysql> select * from blogs;
+----+-----------+--------+-------------+---------------------+---------------------+
| id | title | word | writer | created_at | updated_at |
+----+-----------+--------+-------------+---------------------+---------------------+
| 8 | MyString | MyText | MyText | 2017-01-11 07:33:02 | 2017-01-11 07:33:02 |
| 9 | MyString | MyText | MyText | 2017-01-11 07:33:02 | 2017-01-11 07:33:02 |
| 10 | MyString | MyText | MyText | 2017-01-11 07:33:02 | 2017-01-11 07:33:02 |
| 11 | MyString | MyText | MyText | 2017-01-11 07:33:02 | 2017-01-11 07:33:02 |
| 12 | MyString | MyText | MyText | 2017-01-11 07:33:02 | 2017-01-11 07:33:02 |
| 13 | MyString | MyText | MyText | 2017-01-11 07:33:48 | 2017-01-11 07:33:48 |
| 14 | MyString | MyText | MyText | 2017-01-11 07:33:48 | 2017-01-11 07:33:48 |
+----+-----------+--------+-------------+---------------------+---------------------+

 idが8から12の行のcreated_atのカラムに注目してください!

モデル名の後ろに追加した「生成したいテストデータの数」分、テストデータが同じ時間に作成・登録されています。

 


FactoryGirlと付き合ってみる?


FactoryGirlの便利な機能はこれだけではありません。
連番データの作成や、関連データの作成などなど、
様々なテストデータを作成することができます。

(´-`).。oO(年明けにまとめようかな...)


弊社について


ネオキャリアでは、エンジニアの募集を行っています。
ぜひぜひ、募集記事をチェックしていただけると嬉しいです!

 

www.wantedly.com

www.wantedly.com

 

References

- [いまさら聞けないfactory_girl入門](http://tech.grooves.com/entry/2015/04/28/173025)
- [Everyday Rails - RSpecによるRailsテスト入門](https://leanpub.com/everydayrailsrspec-jp)