RSpecによるモデル単体テストの一連の流れ

環境
Mac 11.0.1
Ruby 2.6.5
Rails 6.0.0
bundlerを使用

テストで使うgem
rspec-rails 4.0.0
factory_bot_rails 6.1.0
faker 2.16.0

タイトルの通り、RSpecによるモデル単体テストの一連の流れを紹介しています。技術的なことに関しては書いていません。ご了承ください。

# 目次
- gemの導入
- FactoryBotを作成する
- ファイルを作成しテストコードを記述する
- テストを実行する
- まとめ
- 今回の気づき

## gemの導入
まずは、Gemfileを開きテストで使うgemを追記します。
上記のgemを`group :development, :test do~end`のなかに記載しましょう。

```: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'       ←追記
  gem 'faker'                   ←追記
end
```

必要なら、pry-railsも導入します。
Gemfileの一番後ろに追記します。

```:Gemfile
gem "pry-rails" ←追記
```

pry-railsはデバッグツールの一つで、作業の際にバグの有無を確認したり、処理を止めてソースコードが正しいかを確認できるものです。'binding.pry'という記述をすると処理を止めてコンソールを起動します。
(参考記事：[デバックツール(pry-rails)について　binding.pryの使い方](https://qiita.com/STHEXA/items/1de2411cb3987066c9b9))

次にターミナルで`bundle install`を実行します。

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

次に、RSpecをインストールします。
ターミナルで`rails g rspec:install`を実行します。

```:ターミナル
% rails g rspec:install
```
これにより以下のファイルやディレクトリが作成されます。

```
.rspec                ファイル
spec                  ディレクトリ
spec/spec_helper.rb   ファイル
spec/rails_helper.rb  ファイル
```

次に、テストの結果をターミナルで可視化するために.rspecに`--format documentation`を追記します。

```:.rspec
--require spec_helper
--format documentation ←追記
```
これで準備は終了です。次は、ファクトリーを作成します。
## FactoryBotを作成する
FactoryBotとは、簡単に言えばモデルのインスタンスを簡単に作成できるようにするものです。

それではファイルを作成しましょう。
ターミナルで`rails g rspec:model モデル名`を実行します。今回モデル名はuserにしておきます。モデル名は単数系で書くようにしましょう。

```:ターミナル
% rails g rspec:model user
```
実行すると以下のファイルやディレクトリが作成されます。

```
spec/models　　　　　　　　　ディレクトリ
spec/models/user_spec.rb  ファイル
spec/factories            ディレクトリ
spec/factories/users.rb   ファイル
```
もしこの時に`factory_bot_rails`を導入していなければ、`spec/factories`と`spec/factories/users.rb`は作成されません。

`factory_bot_rails`をテストコード作成後に導入した場合は、自分でディレクトリとファイルを作成する必要があります。また、自分でfactoryを作成する時は`モデル名の複数形.rb`の名前で作成しましょう。

`spec/models/user_spec.rb`は後で見ていきます。最初に作成された`spec/factories/users.rb `の中身を見てみましょう。

```ruby:spec/models/user_spec.rb
FactoryBot.define do
  factory :user do
    
  end
end
```
`facory :user do ~ end`の中に記述をしていきます。書き方は簡単で`カラム名  {値}`と書けば、指定したカラムに値を設定することができます。今回のuserテーブルの設計は次のようにしておきます。

| Column   | Type   | Option                    |
| -------- | ------ | ------------------------- |
| nickname | string | null: false               |
| email    | string | null: false, unique: true |
| password | string | null: false               |
`spec/models/user_spec.rb`に以下のように追記しましょう。

```ruby:spec/models/user_spec.rb
FactoryBot.define do
  factory :user do
    nickname  {"アプリ君"}
    email     {Faker::Internet.email}
    password  {"password"}
  end
end
```
今回、`email`に対してFakerを使用しました。Fakerは特定の値をランダムで出力してくれるGemです。`Faker::Internet.email`はemailっぽい文字列を出力してくれます。
詳しくは[FakerのGitHub](https://github.com/faker-ruby/faker)をご覧ください。

これでfactoryBotの作成は完了です。

## ファイルを作成しテストコードを記述する
次に、実際にテストコードを書いていきます。
先ほど作成された`spec/models/user_spec.rb`に記述していきます。作成時には以下のような記述がデフォルトで存在します。

```ruby:spec/models/user_spec.rb
require 'rails_helper'

RSpec.describe User, type: :model do
  pending "add some examples to (or delete) #{__FILE__}"
end
```

`RSpec.describe User, type: :model do ~ end`のなかに記述していきます。今回は、モデル単体テストの一連の流れの記事なので、マッチャなどに関しては触れずに進めたいと思います。完成系は以下のようになります。

```ruby:spec/models/user_spec.rb
require 'rails_helper'

RSpec.describe User, type: :model do
  before do
    @user = FactoryBot.build(:user)
  end
  describe "ユーザー管理機能" do
    context "ユーザーの新規登録ができるとき" do
      it "情報が正しければ新規登録できる" do
        expect(@user).to be_valid
      end
    end

    context "ユーザーの新規登録ができないとき" 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
      it "passwordが空では新規登録できない" do
        @user.password = ""
        @user.valid?
        expect(@user.errors.full_messages).to include("Password can't be blank")
      end
    end
  end
end
```

モデルにはバリデーションの記述をするのを忘れないようにしましょう。

## テストを実行する
最後にテストを実行します。
ターミナルで以下を実行しましょう。

```:ターミナル
% bundle exec rspec spec/models/user_spec.rb 
```
緑で表示されているなら、テスト成功です。赤で表示されているところはテストが失敗しているところなので、機能がしっかり実装できていないかテストコードが間違っている可能性があります。

## まとめ
モデル単体テストの一連の流れをまとめると
1. gemの導入
2. factoryを記述
3. テストコードを記述
4. ターミナルで実行

## 今回の気づき
今回、記事で書いたことを確かめるために

1. 新規にアプリケーション作成
2. テストに必要なgemを導入
3. `rails g model user`でモデルを作成

という順番で実行した結果、3のモデル作成時に`spec/models/user_spec.rb`と`spec/factories/users.rb`も一緒に作成されることが判明しました。
もし、アプリケーション完成後にテストを実行する予定があるなら、アプリ新規作成直後にテストに必要なgemを導入しておくのもいいかもしれません。`rails g rspec:model ~~`をする必要がなくなります。

何か間違っているところなどがございましたら、ご指摘いただけると嬉しいです。