#はじめに
以前書いた他の章の記事です。
Rails チュートリアル(3章、4章、5章)をRSpecでテスト
追加しました。
Rails チュートリアル(7章)をRSpecでテスト
Rails チュートリアル(8章)をRSpecでテスト
#テストの準備
factory_bot_rails
はテスト用のデータを作成するため、shoulda-matchers
はバリデーションのテストをするために入れます。(他にも色々なテストで使えるみたいです)
group :development, :test do
gem 'factory_bot_rails'
gem 'shoulda-matchers'
end
$ bundle install
###Shoulda-Matchersの設定
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でユーザーの作成
FactoryBot.define do
factory :user do
name { 'Example User' }
sequence(:email) { |n| "user_#{n}@example.com" }
end
end
###Userモデルバリデーションテスト(name, email)
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)
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にパスワードの追加
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)
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章おわりです。