LoginSignup
10
8

More than 3 years have passed since last update.

Rails チュートリアル(6章)をRSpecでテスト

Last updated at Posted at 2019-08-21

はじめに

以前書いた他の章の記事です。
Rails チュートリアル(3章、4章、5章)をRSpecでテスト

追加しました。
Rails チュートリアル(7章)をRSpecでテスト
Rails チュートリアル(8章)をRSpecでテスト

テストの準備

factory_bot_railsはテスト用のデータを作成するため、shoulda-matchersはバリデーションのテストをするために入れます。(他にも色々なテストで使えるみたいです)

gemfile

group :development, :test do
  gem 'factory_bot_rails'
  gem 'shoulda-matchers'
end
$ bundle install

Shoulda-Matchersの設定

spec/rails_helper.rb

RSpec.configure do |config|
# 省略
end
#--------------追加部分---------------------------
Shoulda::Matchers.configure do |config|
  config.integrate do |with|
    with.test_framework :rspec
    with.library :rails
  end
end
#--------------追加部分---------------------------

テストを書く(6章)

FactoryBotでユーザーの作成

spec/factories/users.rb

FactoryBot.define do
  factory :user do
    name { 'Example User' }
    sequence(:email) { |n| "user_#{n}@example.com" }
  end
end

Userモデルバリデーションテスト(name, email)

spec/models/user_spec.rb

require 'rails_helper'

RSpec.describe User, type: :model do

  #facrory botが存在するかのテストです
  it 'has a valid factory bot' do
    expect(build(:user)).to be_valid
  end
  #ここからバリデーションのテストです
  describe 'validations' do
    it { is_expected.to validate_presence_of(:name) }
    it { is_expected.to validate_presence_of(:email) }
    it { is_expected.to validate_length_of(:name).is_at_most(50) }
    it { is_expected.to validate_length_of(:email).is_at_most(255) }
    it do
      is_expected.to allow_values('first.last@foo.jp',
                                  'user@example.com',
                                  'USER@foo.COM',
                                  'A_US-ER@foo.bar.org',
                                  'alice+bob@baz.cn').for(:email)
    end
    it do
      is_expected.to_not allow_values('user@example,com',
                                      'user_at_foo.org',
                                      'user.name@example.',
                                      'foo@bar_baz.com',
                                      'foo@bar+baz.com').for(:email)
    end

    describe 'validate unqueness of email' do
      let!(:user) { create(:user, email: 'original@example.com') }
      it 'is invalid with a duplicate email' do
        user = build(:user, email: 'original@example.com')
        expect(user).to_not be_valid
      end
      it 'is case insensitive in email' do
        user = build(:user, email: 'ORIGINAL@EXAMPLE.COM')
        expect(user).to_not be_valid
      end
    end
  end
end

ほとんど、shoulda-matchersを使って書いてます。
詳しくはここ↓
thoughtbot/shoulda-matchers -Github

emailのユニークのバリデーションだけshoulda-matchersを使ってないです。使うと以下のように書けます。

it { is_expected.to validate_uniqueness_of(:email).case_insensitive }

ただ、使うとundefined method `downcase!' for nil:NilClassとエラーが出てします。
before_saveが読み込めないみたいだけどなんでかな???

Userモデルbefore_saveのテスト(#email_downcase)

spec/models/user_spec.rb

RSpec.describe User, type: :model do

  # 上記省略

  describe 'before_save' do
    describe '#email_downcase' do
      let!(:user) { create(:user, email: 'ORIGINAL@EXAMPLE.COM') }
      it 'makes email to low case' do
        expect(user.reload.email).to eq 'original@example.com'
      end
    end
  end
end

ここでlet!をを使ってます。だとlet遅延評価され、テスト前にuserがデータベースに登録されず、user.reload.emailの値がnilになってしまいます。
let!を使うことでbefore doみたいに先に実行されるみたいです。

Userモデルのバリデーションテスト(password)

FactoryBotにパスワードの追加

spec/factories/users.rb

FactoryBot.define do
  factory :user do
    name { 'Example User' }
    sequence(:email) { |n| "user_#{n}@example.com" }
    password { 'password' }
    password_confirmation { 'password' }
  end
end

Userモデルのテスト(password)

models/user_spec.rb

require 'rails_helper'

RSpec.describe User, type: :model do
  it 'has a valid factory bot' do
    expect(build(:user)).to be_valid
  end

  # 追加した部分のみ書いてます。
  describe 'validations' do
    describe 'validate presence of password' do
      it 'is invalid with a blank password' do
        user = build(:user, password: ' ' * 6)
        expect(user).to_not be_valid
      end
    end
    it { is_expected.to validate_length_of(:password).is_at_least(6) }
  end
end

パスワードの長さと空文字について検証しています。

本当は空文字の検証もshoulda-matchersで書こうと思ったのですが、空文字が無視されてしまったので、やめました。

ここまでで、6章おわりです。

10
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
8