[RSpec]単体テスト(gem:factory_bot使用)

#RSpec導入
web-consoleは重複しないように注意

```ruby:Gemfile
gem 'rspec-rails'

group :development do
  gem 'web-console'
end
```


`bundle install`後に`rails g rspec:install`

見やすいフォーマットで表示させるために .rspec ファイルを次のように編集

```ruby:.rspec
--format documentation
```
この時点でRSpecが正常に動くか確認しておきましょう。
`bundle exec rspec`

```ruby:ターミナル 
正常に動いていればこのようになる
No examples found.


Finished in 0.00031 seconds (files took 0.19956 seconds to load)
0 examples, 0 failures
```

##作成されるファイル
**.rspec**
**spec**
**spec/spec_helper.rb**
　　rails_helper.rbと同じくRSpec用の共通の設定を書いておくファイルですが、こちらはRSpecをRails無しで利用する際に利用します。

**spec/rails_helper.rb**
　　RailsにおいてRSpecを利用する際に、共通の設定を書いておくファイルです。各テスト用ファイルでこちらのフ　ァイルを読み込むことで、共通の設定や、メソッドを適用

#factory_bot_rails導入
```ruby:Gemfile
group :development, :test do
  #省略
  gem 'rspec-rails'
  gem 'factory_bot_rails'
end
```
**ファイルの作成**
作成したインスタンスの複数形のファイル名でRubyのファイルを作成
spec/factories/`users.eb`となるように今回は作成。

**ファイルの編集**
specファイルの中で特定のメソッドにより簡単にインスタンスを生成したり、DBに保存したりできるようにする

```ruby:user.rb
FactoryBot.define do

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

end
```
##factory_botの基本メソッド
**buildメソッド**
引数にシンボル型で取ったクラス名のインスタンスを、factory_botの記述をもとに作成

```ruby:例
#factory_botを利用しない場合
user = User.new(nickname: "abe", email: "kkk@gmail.com", password: "00000000", password_confirmation: "00000000")
#factory_botを利用する場合
user = FactoryBot.build(:user)
```

**createメソッド**
buildとほぼ同じ働きをしますが、createの場合はテスト用のDBに値が保存されます。
1回のテストが実行され、終了する毎にテスト用のDBの内容がロールバックされます。

```ruby:例
#createしたインスタンスはDBに保存される
user = FactoryBot.create(:user)
```
##factory_botの記法の省略
factory_botによってインスタンスを作成する際に、レシーバーであるクラスのFactoryBotという記述を省略することができます。

```ruby:rails_helper.rb
#省略
RSpec.configure do |config|
  #下記の記述を追加
  config.include FactoryBot::Syntax::Methods

  #省略

end
```

#モデルのテストコードを書く
`Userモデル`のテストコード
**specファイルの作成**
ファイルの命名規則`対応するクラス名_spec.rb`

spec/models/user_spec.rbとなるように作成する。

```ruby:user_spec.rb
require 'rails_helper'
describe User do
  describe '#create' do
    it "nicknameがない場合は登録できないこと" do
      user = build(:user, nickname: "")
      user.valid?
      expect(user.errors[:nickname]).to include("can't be blank")
    end
  end
end
```
##コードの説明
**describe**
describeは、直後のdo ~ endまでのテストのまとまりを作ります。describeの後に続く""の中にはそのまとまりの説明を書きます。

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

**エクスペクテーション**
実際に評価される式のことです。it do ~ endの間に書きます。上記の式では`expect(user.errors[:nickname]).to include("can't be blank")`の部分がエクスペクテーションです。

**マッチャ**
エクスペクテーションの中で、テストが成功する条件を示します。


#メソッド
**valid?**
「バリデーションにより保存ができない状態であるか」を確かめる
メソッドの返り値はtrue/false

**errors**
valid?メソッドを利用したインスタンスに対してerrorsメソッドを利用すると、バリデーションにより保存ができない状態である場合なぜできないのかを確認する


#マッチャ
**include**
引数にとった値がexpectの引数である配列に含まれているかをチェックすることができる
　　重複に関するパターン：has already been taken
　　空のパターン：can't be blank
　　文字数が足らないパターン：is too short
　　文字数が多すぎるパターン：is too long

**be_valid**
expectの引数にしたインスタンスが全てのバリデーションをクリアする場合にパスします。
下記例

```ruby:sample_spec.rb
it "nicknameが6文字以下では登録できること " do
  user = build(:user, nickname: "aaaaaa")
  expect(user).to be_valid
end
```

**eq**
等しければパスします。下記に例

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