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