[rails][devise][初心者]rspecでテストコードを書きながら学ぶ

# はじめに
deviseを使用したユーザー登録のテストコードを書いたので、備忘録として書き残します。
なお、内容はとても簡単な、初学者向けのものなります。

### 使用Gem等

- ruby, 2.5.1
- rails, ~> 5.2.3
- devise
- rspec-rails, ~>3.5
- factory_bot_rails

上記のGemをインストールします。
なお、web_console というgemはtest環境で動かすと不具合が起きる可能性があるgemなのでdevelopment環境でのみ動くようにします。
group :development do ~ endの記述が無ければ作成し、既にあればその記述の間にweb_consoleを移動させます。

## Rspecの設定ファイルを作成
ターミナルで下記のコマンドを実行します。

````
rails g rspec:install
````
すると以下のファイルが作成されます。

````
create  .rspec
create  spec
create  spec/spec_helper.rb
create  spec/rails_helper.rb
````

#### rails_helper.rb
RailsにおいてRSpecを利用する際に、共通の設定を書いておくファイルです。各テスト用ファイルでこちらのファイルを読み込むことで、共通の設定や、メソッドを適用します。
#### spec_helper.rb
rails_helper.rbと同じくRSpec用の共通の設定を書いておくファイルですが、こちらはRSpecをRails無しで利用する際に利用します。
#### specファイル
RSpecによるテストコードが書かれたファイルのことを、specファイルと呼びます。全てのspecファイルは、先ほどのrails g rspec:installコマンドで生成された「specディレクトリ」の中に格納しておきます。
モデルに関するテスト用ファイルであればspec/models/以下に、コントローラーに関するテスト用ファイルであればspec/controllers/以下に格納されます。appディレクトリ以下にあるテストの対象となるコードの在り処と対応させます。
#### specファイルの命名規則
specファイルは対応するクラス名_spec.rbという名前になります。今回はまず「user.rb」に関するspecファイルを作成するので、その場合の名前は「user_spec.rb」になります。

### .rspecに以下を記述

````.rspec
--format documentation
````
これで準備はrspecの準備は完了です。

## factory_botの設定
ダミーのインスタンスを作成するために、factory_botを設定していきます。

````spec/factories/users.rb
FactoryBot.define do

  factory :user do
    name                  {"abe"}
    email                 {"abe@gmail.com"}
    password              {"00000000"}
    password_confirmation {"00000000"}
  end

end
````

#### factory_bot
簡単にダミーのインスタンスを作成することができるGemです。他のファイルで予め各クラスのインスタンスに定めるプロパティを設定しておき、specファイルからメソッドを利用してその通りのインスタンスを作成します。factory_botを利用すれば、user_spec.rbは以下のように短い記述にすることができます。

````user_spec.rb
user = User.new(name: "abe", email: "abe@gmail.com", password: "00000000", password_confirmation: "00000000")

# これがfactory_botを使用すると以下のようにできます

user = build(:user)
````

### buildメソッド, createメソッド
buildメソッド、createメソッドはfactory_botにおける最も基本的なメソッドです。
##### buildメソッド
引数にシンボル型で取ったクラス名のインスタンスを、factory_botの記述をもとに作成します。
##### createメソッド
buildとほぼ同じ働きをしますが、createの場合はテスト用のDBに値が保存されます。
注意すべき点として、1回のテストが実行され、終了する毎にテスト用のDBの内容がロールバックされます。（保存された値がすべて消去されてしまう）
従って、binding.pry等でテストの実行を一時停止しないとテスト用のDBに保存された値を確認することはできません。 

これで、factory_botの準備も整いました。

## テストコードを書く
テストコードは以下のように書いていきます。

````sample_spec.rb
describe "hogehoge" do
  it "1 + 1は2になること" do
    expect(1 + 1).to eq 2
  end
end
````

#### describe
1行目のdescribeは、直後のdo ~ endまでのテストのまとまりを作ります。describeの後に続く""の中にはそのまとまりの説明を書きます。

#### itとexample
2行目のitはexampleと呼ばれる実際に動作するテストコードのまとまりを表します。itの後に続く""の中にはそのexampleの説明を書きます。

#### エクスペクテーション
実際に評価される式のことです。it do ~ endの間に書きます。上記の式ではexpect(1 + 1).to eq 2の部分がエクスペクテーションです。

#### expect(X).to eq Y
エクスペクテーションの文法です。xの部分に入れた式の値がYの部分の値と等しければ、テストが成功します。eqの部分を、マッチャと言います。

#### マッチャ
エクスペクテーションの中で、テストが成功する条件を示します。例えばeqは「等しければ」という意味になります。他にも
include(含んでいれば)、valid(バリデーションされれば)など複数のマッチャが存在します。

## 実際に書いてみる
ユーザー登録時にnameがなければ登録ができないことをテストします。
そのため、factory_botで設定したダミーインスタンスを、nameをnilで作成します。

````spec/models/user_spec.rb
describe User do

  describe '#create' do
    it "nameがない場合は登録できないこと" do
      # userインスタンスのnameをnilでbuildします
      user = build(:user, name: nil)
      # 作成したインスタンスがバリデーションによって保存ができない状態かチェックする
      user.valid?
      # エラー文が入った配列を取り出し、includeマッチャを利用してエクスペクテーションを作る
      expect(user.errors[:nickname]).to include("can't be blank")
    end
  end

end
````

次に、テストを実行します。以下のコマンドをターミナルで実行します。


````
bundle exec rspec
````

以下のように表示されれば成功です。

````
User
  #create
    nameがない場合は登録できないこと

Finished in 0.53132 seconds (files took 3.64 seconds to load)
1 example, 0 failures
````

# おわり
以上で簡単なテストを行うことが出来ました。
色々とまとまりのない記事になってしまったので、内容を分けて再度投稿するかもしれません。
最後まで読んでいただき、ありがとうございました。