RailsチュートリアルのテストをRspecで書いてみた[第6章]

はじめに

今回はRspecの学習の一環として、RailsチュートリアルのテストをRspecで書いていきます。
至らない点があるかもしれませんが、その際はコメントにてご指摘をお願いします。

各種バージョン

Ruby 2.7.0
Rails 6.0.3.3
Rspec 3.9
Capybara 3.33.0
Factory_bot_rails 6.1.0

第6章

リスト6.5: 有効なUserかどうかをテストする

このテストからFactoyBotを使用しています。

spec/factories/user.rb

FactoryBot.define do
  factory :user do
    name { "TestUser" }
    email { "test@example.com" }
  end
end
spec/models/user_spec.rb

require 'rails_helper'

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

  it 'should be valid' do
    expect(user).to be_valid
  end
end

リスト6.7: name属性へのバリテーションに対するテスト

spec/models/user_spec.rb

require 'rails_helper'

RSpec.describe User, type: :model do
  let(:user) { FactoryBot.build(:user) }
・・・
  it 'is invalid with no name' do
    user.name = ' '
    expect(user).to be_invalid
  end
end

リスト6.11: email属性へのバリテーションに対するテスト

spec/models/user_spec.rb

require 'rails_helper'

RSpec.describe User, type: :model do
  let(:user) { FactoryBot.build(:user) }
・・・
  it 'is invalid with no mail' do
    user.mail = ' '
    expect(user).to be_invalid
  end
end

リスト6.14: nameとemailの長さの検証に対するテスト

spec/models/user_spec.rb

require 'rails_helper'

RSpec.describe User, type: :model do
  let(:user) { FactoryBot.build(:user) }
・・・
    it 'is invalid with 51-letter names' do
    user.name = 'a' * 51
    expect(user).to be_invalid
  end

  it 'is invalid with 256-letter mails' do
    user.name = 'a' * 244 + 'example.com'
    expect(user).to be_invalid
  end
end

リスト6.18: 有効なメールフォーマットをテストする

spec/models/user_spec.rb

RSpec.describe User, type: :model do
  let(:user) { FactoryBot.build(:user) }
・・・
  it 'is valid with the correct email\'s format' do
    valid_addresses = %w(user@example.com USER@foo.COM A_US-ER@foo.bar.org
                          first.last@foo.jp alice+bob@baz.cn)
    valid_addresses.each do |valid_address|
      user.email = valid_address
      expect(user).to be_valid 
    end
  end
end

リスト6.19: メールフォーマットの検証に対するテスト

spec/models/user_spec.rb

RSpec.describe User, type: :model do
  let(:user) { FactoryBot.build(:user) }
・・・
  it 'is invalid with the wrong email\'s format' 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 be_invalid
    end
  end
end

リスト6.24: 重複するメールアドレス拒否のテスト

spec/models/user_spec.rb

RSpec.describe User, type: :model do
  let(:user) { FactoryBot.build(:user) }
・・・
  it "is invalid with registered email" do
    duplicate_user = user.dup
    user.save
    expect(duplicate_user).to be_invalid
  end
end

リスト6.26: 大文字小文字を区別しない、一意性のテスト

spec/models/user_spec.rb

RSpec.describe User, type: :model do
  let(:user) { FactoryBot.build(:user) }
・・・
  it "is invalid with registered email" do
    duplicate_user = user.dup
    duplicate_user.email = user.email.upcase
    user.save
    expect(duplicate_user).to be_invalid
  end
end

リスト6.40: パスワードとパスワード確認を追加する

ここでは「has_secure_password」を使用することになり、testが通らなくなるので「spec/factories/user.rb」を修正します。
また、emailカラムが一意なので後々のことを考えて、「sequence」を使用したいと思います。
「sequence」を使用するとテスト用のオブジェクトが生成される度に、 一意の値を生成してくれます。

spec/factories/user.rb

FactoryBot.define do
  factory :user do
    name { "TestUser" }
    sequence(:email) { |n| "test#{n}@example.com" } #<=一意の値を生成してくれる。
#下記追加
    password { "foobar" }
    password_confirmation { "foobar" }
  end
end

リスト6.42: パスワードの最小文字数をテストする

spec/models/user_spec.rb

RSpec.describe User, type: :model do
  let(:user) { FactoryBot.build(:user) }
・・・
  it 'is invalid with no password' do
    user.password = user.password_confirmation = ' ' * 6
    expect(user).to be_invalid
  end

  it 'is invalid with 5-letter passwords' do
    user.password = user.password_confirmation = 'a' * 5
    expect(user).to be_invalid
  end
end