Railsでポートフォリオを作ってみよう！ vol.4 (RSpec・FactoryBot編 後編)

 
前回までで一通りの導入から設定は完了した為、今回はテストの実装を行う。
今回はRailsTutorialの流れでは第6章を実装するが、簡略しているところがほとんどなので、もっと細かく知りたい人は調べてみてほしい。

#テストの実装
テストを実装する。第6章はUserモデルのバリデーションについてのテストが多いためそこをピックアップして実装する。

## FactoryBotを使ってみよう
前回導入を行なったFactoryBotを使い、テストユーザーのセットアップを行う。

```
$ docker-compose run web bin/rails g factory_bot:model user
```

を実行後user.rbが作成されるため

```spec/factories/users.rb
#現在のFactoryBotのVerでは以下の書き方は非推奨となっている
#後ほど詳しく説明する
FactoryBot.define do
  factory :user do
    name "ExampleUser"
    nickname "Example"
    sequence(:email) { |n| "tester#{n}@example.com" }
    self-introduction "Testintroduction"
    password "password"
    password_confirmation "password"
  end
end
```

を打つ。
FactoryBot4.11?以降から静的属性が非推奨になってしまった。使用を続けることはできるが、テストを走らせると

```
DEPRECATION WARNING: Static attributes will be removed in FactoryBot 5.0. Please use dynamic
attributes instead by wrapping the attribute value in a block:
```

といった警告文が出てくる。
そのため

```spec/factories/users.rb
FactoryBot.define do
  factory :user do
    name { "ExampleUser" }
    nickname { "Example" }
    sequence(:email) { |n| "tester#{n}@example.com" }
    self-introduction { "Testintroduction" }
    password { "password" }
    password_confirmation { "password" }
  end
end
```

という感じに修正を行う。
または、rubicon-rspecと呼ばれるgemに

```
rubocop \
  --require rubocop-rspec \
  --only FactoryBot/AttributeDefinedStatically \
  --auto-correct
```

を入れれば一括で修正を行ってくれる。

##テストの作成

spec/models/user_spec.rbを作成し、name、email、passwordのバリデーションテストを実装する。

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

RSpec.describe User, type: :model do
  let(:user) { FactoryBot.create(:user) }

  describe User do 
    it "有効なファクトリを使用していること" do 
      expect(user).to be_valid
    end
  end

  it "重複したメールアドレスは無効になること" do 
    FactoryBot.create(:user, email: "Exple@example.com")
    user = FactoryBot.build(:user, email: "example@example.com")
    user.valid?
    expect(user.errors[:email]).to include("has already been taken")
  end

  describe "メールアドレスの有効性についてのテスト" do
    it "無効なメールアドレスの場合使用できないこと" do
      invalid_addresses = %w[user@example,com user_at_foo.org user.name@example. 
                            foo@bar_baz.com foo@bar+baz.com]
      invalid_addresses.each do |invalid_address|
        user.email = invalid_address
        expect(user).to_not be_valid
      end
    end

    it "有効なメールアドレスの場合使用できること" do
      valid_addresses = %w[user@foo.COM A_US-ER@f.b.org frst.lst@foo.jp a+b@baz.cn]
      valid_addresses.each do |valid_address|
        user.email = valid_address
        expect(user).to be_valid
      end
    end
  end

  describe "パスワードについてのテスト" do
    it "パスワードが一致しない場合無効になること" do
      user = FactoryBot.build(:user, password: "password", password_confirmation: "different")
      user.valid?
      expect(user.errors[:password_confirmation]).to include("doesn't match Password")
    end

　　it "パスワードが一致した場合有効になること" do
      user = FactoryBot.build(:user, password: "password", password_confirmation: "password")
      expect(user).to be_valid
    end
  end
end
```

テストが記入できたら保存を行い、

```
$ docker-compose run web bundle exec rspec
```

を実行し、全てパスすれば成功。

#各種説明

###require 'rails_helper'
rails_helperを呼び出している。
どんなテストにも書かなければならないので、お約束みたいなもの。

### type: :model 
書かれるテストの種類を指定する。
modelの他にもfeatureやcontoroller、systemなどがある。

### it do
itの後ろにテストの内容を記入する
自分は英語ダメダメなので現状は日本語で書いているが、英語で書いている人も多い。