【Rails】ユーザー管理機能実装　Userモデル単体テスト実施

# ユーザー管理機能のモデル単体テスト
https://qiita.com/shintech9898/items/cb048052267f1adecbd1
上記にてユーザー管理機能の実装が完了したのでモデル単体テストを実施していく。
### Gemfileを編集。
```ruby:Gemfile
group :development, :test do
  # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
  gem "debug", platforms: %i[ mri mingw x64_mingw ]
  gem 'rspec-rails', '~> 4.0.0'
  gem 'factory_bot_rails'
  gem 'faker'
end
```

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

### テストコードを記述するファイルを生成
ターミナル
```
% rails g rspec:model user
```
テスト実行時の出力形式を「ドキュメント形式」に変更するため下記コードをr.specファイルに追記する。
このオプションを使用すると、テスト結果がより読みやすくなり、各テストケースの説明が詳細に表示される。

```ruby:r.spec
--format documentation
```

### Factorybotでユーザーを定義する
```ruby:spec/factories/user.rb
FactoryBot.define do
  factory :user do
    nickname              { Faker::Name.initials(number: 2) }
    email                 { Faker::Internet.email }
    password              { 'password123' }
    password_confirmation { password }
    first_name            { '太郎' }
    last_name             { '山田' }
    first_name_kana       { 'タロウ' }
    last_name_kana        { 'ヤマダ' }
    birth_date            { Faker::Date.birthday(min_age: 18, max_age: 65) }
  end
end
```

### バリデーションを確認してテスト項目を洗い出す。
### 登録が成功する場合

- nickname、email、password、password_confirmation、first_name、last_name、first_name_kana、last_name_kana、birth_dateが存在すれば登録できる

### 登録が失敗する場合

- nicknameが空では登録できない
- emailが空では登録できない
- passwordが空では登録できない
- passwordとpassword_confirmationが不一致では登録できない
- 重複したemailが存在する場合は登録できない
- emailは@を含まないと登録できない
- passwordが5文字以下では登録できない
- passwordが129文字以上では登録できない
- passwordが数字のみでは登録できない
- passwordが英字のみでは登録できない
- passwordに全角文字が含まれていると登録できない
- first_nameが空では登録できない
- last_nameが空では登録できない
- first_nameは全角（漢字・ひらがな・カタカナ）でないと登録できない
- last_nameは全角（漢字・ひらがな・カタカナ）でないと登録できない
- first_name_kanaが空では登録できない
- last_name_kanaが空では登録できない
- first_name_kanaは全角（カタカナ）でないと登録できない
- last_name_kanaは全角（カタカナ）でないと登録できない
- birth_dateが空では登録できない

### 上記で洗い出した内容のテストコードを記述していく。
```ruby:/spec/models/use_spec.rb
require 'rails_helper'

RSpec.describe User, type: :model do
  before do
    @user = FactoryBot.build(:user)
  end
  describe 'ユーザー新規登録' do
    context '新規登録できるとき' do
      it 'nicknameとemail、passwordとpassword_confirmation、first_nameとlast_name、first_name_kanaとlast_name_kana、birth_dateが存在すれば登録できる' 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.password_confirmation = ''
        @user.valid?
        expect(@user.errors.full_messages).to include "Password can't be blank"
      end
      it 'passwordとpassword_confirmationが不一致では登録できない' do
        @user.password = '1234aaa'
        @user.password_confirmation = '1234asd'
        @user.valid?
        expect(@user.errors.full_messages).to include "Password confirmation doesn't match Password"
      end
      it '重複したemailが存在する場合は登録できない' do
        @user.save
        another_user = FactoryBot.build(:user)
        another_user.email = @user.email
        another_user.valid?
        expect(another_user.errors.full_messages).to include 'Email has already been taken'
      end
      it 'emailは@を含まないと登録できない' do
        @user.email = 'hogehoge'
        @user.valid?
        expect(@user.errors.full_messages).to include 'Email is invalid'
      end
      it 'passwordが5文字以下では登録できない' do
        @user.password = '123aa'
        @user.password_confirmation = '123aa'
        @user.valid?
        expect(@user.errors.full_messages).to include 'Password is too short (minimum is 6 characters)'
      end
      it 'passwordが129文字以上では登録できない' do
        @user.password = Faker::Internet.password(min_length: 129, max_length: 150)
        @user.password_confirmation = @user.password
        @user.valid?
        expect(@user.errors.full_messages).to include 'Password is too long (maximum is 128 characters)'
      end
      it 'passwordは数字のみは登録できない' do
        @user.password = '1234567'
        @user.password_confirmation = '1234567'
        @user.valid?
        expect(@user.errors.full_messages).to include 'Password is invalid. Include both letters and numbers'
      end
      it 'passwordは英字のみでは登録できない' do
        @user.password = 'aaaaaaa'
        @user.password_confirmation = 'aaaaaaa'
        @user.valid?
        expect(@user.errors.full_messages).to include 'Password is invalid. Include both letters and numbers'
      end
      it 'passwordは全角が含まれると登録はできない' do
        @user.password = 'あaaa111'
        @user.password_confirmation = 'あaaa111'
        @user.valid?
        expect(@user.errors.full_messages).to include 'Password is invalid. Include both letters and numbers'
      end
      it 'first_nameは空では登録できない' do
        @user.first_name = ''
        @user.valid?
        expect(@user.errors.full_messages).to include "First name can't be blank"
      end
      it 'last_nameは空では登録できない' do
        @user.last_name = ''
        @user.valid?
        expect(@user.errors.full_messages).to include "Last name can't be blank"
      end
      it 'first_nameは全角（漢字・ひらがな・カタカナ）でないと登録できない' do
        @user.first_name = 'aaa'
        @user.valid?
        expect(@user.errors.full_messages).to include 'First name is invalid. Input full-width characters'
      end
      it 'last_nameは全角（漢字・ひらがな・カタカナ）でないと登録できない' do
        @user.last_name = 'aaa'
        @user.valid?
        expect(@user.errors.full_messages).to include 'Last name is invalid. Input full-width characters'
      end
      it 'first_name_kanaは空では登録できない' do
        @user.first_name_kana = ''
        @user.valid?
        expect(@user.errors.full_messages).to include "First name kana can't be blank"
      end
      it 'last_name_kanaは空では登録できない' do
        @user.last_name_kana = ''
        @user.valid?
        expect(@user.errors.full_messages).to include "Last name kana can't be blank"
      end
      it 'first_name_kanaは全角（カタカナ）でないと登録できない' do
        @user.first_name_kana = 'aaa'
        @user.valid?
        expect(@user.errors.full_messages).to include 'First name kana is invalid. Input full-width katakana characters'
      end
      it 'last_name_kanaは全角（カタカナ）でないと登録できない' do
        @user.last_name_kana = 'aaa'
        @user.valid?
        expect(@user.errors.full_messages).to include 'Last name kana is invalid. Input full-width katakana characters'
      end
      it 'birth_dateが空では登録できない' do
        @user.birth_date = ''
        @user.valid?
        expect(@user.errors.full_messages).to include "Birth date can't be blank"
      end
    end
  end
end
```
describeに「どの機能に対してのテストを行うか」を記し、その中ではcontextによって「新規登録できる場合/できない場合」という、「特定の条件」に基づいたグループ分けを行う。
contextの中では、itを用いて詳細なテスト項目を記してる。

### テストの実行
ターミナル
```
% bundle exec rspec spec/models/user_spec.rb
```

### 回答：
```
User
  ユーザー新規登録
    新規登録できるとき
      nicknameとemail、passwordとpassword_confirmation、first_nameとlast_name、first_name_kanaとlast_name_kana、birth_dateが存在すれば登録できる
    新規登録できないとき
      nicknameが空では登録できない
      emailが空では登録できない
      passwordが空では登録できない
      passwordとpassword_confirmationが不一致では登録できない
      重複したemailが存在する場合は登録できない
      emailは@を含まないと登録できない
      passwordが5文字以下では登録できない
      passwordが129文字以上では登録できない
      passwordは数字のみは登録できない
      passwordは英字のみでは登録できない
      passwordは全角が含まれると登録はできない
      first_nameは空では登録できない
      last_nameは空では登録できない
      first_nameは全角（漢字・ひらがな・カタカナ）でないと登録できない
      last_nameは全角（漢字・ひらがな・カタカナ）でないと登録できない
      first_name_kanaは空では登録できない
      last_name_kanaは空では登録できない
      first_name_kanaは全角（カタカナ）でないと登録できない
      last_name_kanaは全角（カタカナ）でないと登録できない
      birth_dateが空では登録できない

Finished in 0.37605 seconds (files took 1.82 seconds to load)
21 examples, 0 failures

```
上記を確認し、Userモデルの単体テスト完了。