[Rails] テストコードでFactoryBotを使う

## はじめに
前回RSpecによるテストコードの概要とRSpecの導入をアウトプットしました。
今回はどうせなので、RSpec導入したらほぼ確実にこれも使うでしょっていうFactoryBotの導入の仕方と説明をまとめてみました。よろしくお願いします。

また、例としてUserモデルの単体テストコードを書いていくことを想定して説明していきたいと思います。

## FactoryBotの導入
テストコードでは、例えばUserモデルのテストコードを書く際に、まず適当に名前やE-mailアドレス、パスワードなどの情報を入力してあげないといけません。
user = User.new(nickname: 'aaaaa', email: 'test＠example.com', password: '000000', password_confirmation: '000000')と言った具合に。

しかしこのような記述を毎回毎回記述するのは面倒なので、繰り返し同じような記述するのはまとめてしまった方が効率的ですね。そこで活躍するのがFactoryBotさんです！

FactoryBotは他のファイルにあらかじめ各クラスのインスタンスに上記のような定める値を設定しておき、各テストコードで使用します。また、GemなのでGemfileに書き込んでbundle installしてやる必要があります。

とりあえず、導入していきましょう。
Gemfileの中の**group :development, test do　**の中に記述します

```Ruby:Gemfile
group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
  gem 'rspec-rails', '~> 4.0.0'
  gem 'factory_bot_rails'
end
```
続いてbundle install

```terminal:ターミナル
% bundle install
```

## 実際にFactoryBotを使う

導入が完了したら、続いて、手動で **spec**というディレクトリに**factories**というディレクトリを作成し、さらにその中に**users.rb**というファイルを作成します。これはUserモデルに対するFactoryBotのファイルになります。
**spec/factories/users.rb**という構造です。

今作成したファイルを下記のように編集します。

```Ruby:spec/factories/users.rb
FactoryBot.define do
  factory :user do
    nickname              {'test'}
    email                 {'test@example'}
    password              {'000000'}
    password_confirmation {password}
  end
end
```

これでまとめられました。このファイルを使うために**build**というメソッドを使います。

newメソッドを使って

```
user = User.new(nickname: 'test', email: 'test@example', password: '000000', password_confirmation: '00000000')
```

こんなふうにしてたのが、buildを使って先ほどのFactoryBotを使うと

```
user = FactoryBot.build(:user)
```

これで同じ記述をしていることになります。だいぶこの方が楽ですよね。
これを使ってテストを書いてみると

```spec/models/user_spec.rb
require 'rails_helper'
RSpec.describe User, type: :model do
  describe 'ユーザー新規登録' do
    it 'nicknameが空では登録できない' do
      user = FactoryBot.build(:user)  # Userのインスタンス生成
      user.nickname = ''  # nicknameの値を空にする
      user.valid?
      expect(user.errors.full_messages).to include "Nickname can't be blank"
    end
    it 'emailが空では登録できない' do
      user = FactoryBot.build(:user)  # Userのインスタンス生成
      user.email = ''  # emailの値を空にする
      user.valid?
      expect(user.errors.full_messages).to include "Email can't be blank"
    end
  end
end
```

こんな感じになります。しかし、これでもまだ毎回毎回　user = FactoryBot.build(:user)っていう記述を書くの？ってなりませんか？

そこで**before**を使います。
テストを書き始める前に**before do ~ end**の間に処理を書くと、テストコード実行前にセットアップしてくれます。

先ほどの定義してたuserという変数はインスタンス変数＠userにしてあげないといけませんので注意してください。それでは、これらを踏まえて変更したのが下記になります。

```spec/models/user_spec.rb
require 'rails_helper'
RSpec.describe User, type: :model do
  before do
    @user = FactoryBot.build(:user)
  end

  describe 'ユーザー新規登録' do
    it 'nicknameが空では登録できない' do
      @user.nickname = ''
      @user.valid?
      expect(@user.errors.full_messages).to include "Nickname can't be blank"
    end
    it 'emailが空では登録できない' do
      @user.email = ''
      @user.valid?
      expect(@user.errors.full_messages).to include "Email can't be blank"
    end
  end
end
```

このようにまとめると見やすくなりますし、書いてる側も楽ですよね！

最後に下記のコマンドを実行し、テストコードが成功するか確認して終わりにしましょう

```terminal:ターミナル
% bundle exec rspec spec/models/user_spec.rb
```

## 最後に
RspecでFactoryBotを使用は必須かと思います。これも毎回導入しないといけないGemなので導入方法から使い方までしっかり覚えられるようにしていきたいです。