Rspecの導入と単体テストコード

テストは非常に重要だけど、避けていました、、、笑
しっかり復習していきます！

### 目的
- RSpecでテストのテストの書く準備
- 基本てみなテストコードの書き方理解
- テストコードの実行方法を理解

### バリデーション設定
app/models/user.rb
```ruby
validates :nickname, presence: true
```

### RspecのGem追加
Gemfile
```ruby
〜　略〜
group :development, :test do
    gem 'rspec-rails', '~> 4.0.0'
end
```
ターミナル
`bundle install`

### RSpec設定
`rails g rspec:install`

テストコードの結果をターミナル上に可視化する
.rspec
`--format documentation`

### テストファイル作成
`rails g rspec:model user

spec/models/user_spec.rb
```ruby
require 'rails_helper'
```
RSpecでモデル、ビュー、コントローラーのテストを行うためには、　_*rails_helper.rb*_ 
というファイルを読み込む必要がある

#### rails_helper
共通の設定を書いておくファイル

###　モデル単体テスト
#### describe
テストコードのグループ分けを行うメソッド
「どの機能に対してのテストを行うのか」をdescribeでグループ分けし、その中に各テストコードを記述します
```ruby
describe '' do
    describe '' do
    
    end
end
```

#### it
より詳細に、　「describeメソッドに記述した機能において、どのような状況のテストを行うか」を明記

#### example
itで分けたグループ


例）
２つのexampleに関するテストコードを記述
- nicknameが空では登録できない
- emailが空では登録できない

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

RSpec.describe User, type: :model do
  describe 'ユーザー新規登録' do
    it 'nicknameが空では登録できない' do
      # nicknameが空では登録できないテストコードを記述します
    end
    it 'emailが空では登録できない' do
      # emailが空では登録できないテストコードを記述します
    end
  end
end
```
#### bundle execコマンド
Gemの依存関係を整理してくれるコマンド

#### rspecコマンド
RSpecのテストコードを実行するコマンド

ターミナル
`bundle exec rspec spec/models/user_spec.rb`
```
結果が緑色で表示されれば成功

### nicknameが空の場合の記述(異常系)
異常系のモデル単体テストの実装は、
1. 保存するデータ(インスタンス)を作成
1. 作成したデータ(インスタンス)が保存されるかどうかを確認
1. 保存されない場合、生成されるエラーメッセージが想定されるものかどうか確認

nicknameのバリデーションに指定されている、`presence:true`の挙動検証

```ruby
describe 'ユーザー新規登録' do
    it 'nicknameが空だと登録できない' do
user = User.new()nickname: '', email: 'test@example', password: '000000', password_confirmation: '000000'
end
```
＊バリデーションはDBに保存する前しか実行されません。

#### valid?
バリデーションを実行させて、エラーがあるかどうかを判断するメソッド
なし: true あり: false
エラー内容を示すエラーメッセージを生成
ターミナル
```
rails c
[1] pry(main)> user = User.new(nickname: '')
[2] pry(main)> user.valid?
=> false
```

```ruby
   it 'nicknameが空だと登録できない' do
      user = User.new(nickname: '', email: 'test@example', password: '000000', password_confirmation: '000000')
      user.valid?
    end
```

#### expectation
検証で得られた挙動が想定通りなのかを確認する構文のこと
#### matcher
「`expect`の引数」と「想定した挙動」が一致しているかどうかを判断

雛形　`expect().to matcher()`

#### include
「`expect`の引数」に「`include`の引数」が含まれていることが確認するマッチャ
例)
```ruby
describe 'フルーツ盛り合わせ' do
  it 'フルーツ盛り合わせにメロンが含まれている' do
     expect(['りんご', 'バナナ', 'ぶどう', 'メロン']).to include('メロン')
  end
end
```
#### eq
「`expect`の引数」と「`eq`の引数」が等しいことを確認するマッチャ
例）
```ruby
describe '加算' do
  it '1 + 1の計算結果は2と等しい' do
     expect(1 + 1).to eq(2)
  end
end
```

#### errors
インスタンスにエラーを示す情報がある場合、その内容を返すメソッド
例）
ターミナル
```
rails c
[1] pry(main)> user = User.new(nickname: '', email: 'test@example', password: '000000', password_confirmation: '000000')
[2] pry(main)> user.valid?
User Exists? (10.4ms)  SELECT 1 AS one FROM `users` WHERE `users`.`email` = BINARY 'test@example' LIMIT 1
=> false
[3] pry(main)> user.errors
=> #<ActiveModel::Errors [#<ActiveModel::Error attribute=nickname, type=blank, options={}>]>
```
`nickname` で `blank`というエラーが起こっている

#### full_messages
エラーの内容から、エラーメッセージを配列として取り出すメソッド
ターミナル
```
[4] pry(main)> user.errors.full_messages
=> ["Nickname can't be blank"]
```

spec/models/user_spec.rb
```ruby
describe 'ユーザー新規登録' do
    it 'nicknameが空では登録できない' do
      user = User.new(nickname: '', email: 'test@example', password: '000000', password_confirmation: '000000')
      user.valid?
      expect(user.errors.full_messages).to include("Nickname can't be blank")
    end
```

テストコード実行
`bundle exec rspec spec/models/user_spec.rb`

emailも同様に
#### エラーメッセージ確認
`binding.pry`　を用いてエラーを確認
spec/models/user_spec.rb


```ruby
 it 'emailが空では登録できない' do
      user = User.new(nickname: 'test', email: '', password: '000000', password_confirmation: '000000')
      user.valid?
      binding.pry
    end
```
`bundle exec rspec spec/models/user_spec.rb`

ターミナル
```
[1] pry(main)> user.errors
=> #<ActiveModel::Errors:0x00007fba4d3e0a80
 @base=#<User id: nil, email: "", created_at: nil, updated_at: nil, nickname: "test">,
 @details={:email=>[{:error=>:blank}]},
 @messages={:email=>["can't be blank"]}>
[2] pry(main)> user.errors.full_messages
=> ["Email can't be blank"]
```

["Email can't be blank"]というエラーメッセージを踏まえてエクスペクテーション記述
expectにはエラーメッセージの配列を、includeには想定しているエラーメッセージを記述

spec/models/user_spec.rb
```ruby
it 'emailが空では登録できない' do
      user = User.new(nickname: 'test', email: '', password: '000000', password_confirmation: '000000')
      user.valid?
      expect(user.errors.full_messages).to include("Email can't be blank")
    end
```

テスト実行
`bundle exec rspec spec/models/user_spec.rb `

完成コード


```ruby
require 'rails_helper'

RSpec.describe User, type: :model do
  describe 'ユーザー新規登録' do
    it 'nicknameが空では登録できない' do
      user = User.new(nickname: '', email: 'test@example', password: '000000', password_confirmation: '000000')
      user.valid?
      expect(user.errors.full_messages).to include("Nickname can't be blank")
    end
    it 'emailが空では登録できない' do
      user = User.new(nickname: 'test', email: '', password: '000000', password_confirmation: '000000')
      user.valid?
      expect(user.errors.full_messages).to include("Email can't be blank")
    end
  end
end
```