RSpecでsubjectを使用して、配列を
subject { user.errors[:name] }
このように検査時、配列の長さを取得する方法が分からなかったので調べました。
結論
rspec-its
のits
を使用する。
its(:size) { is_expected.to eq 3 }
のように書くとsubjectの検査対象の配列の長さを取得できます。
経緯
モデルのテストを書きました。
modelのコード↓
class User < ApplicationRecord
validates :nickname, presence: true, length: { maximum: 32 },
format: { with: /\A[-0-9a-zA-Z#$%&()._]*\z/,
message: 'には半角英数字と#$%&()-._のみ使用できます。' }
end
テストは以下のようになります。(全て書くと長いので一部のみ抜粋)
require 'rails_helper'
RSpec.describe User, type: :model do
describe '#nickname' do
context '空白のとき'do
it 'エラーが出ること' do
user = User.new(nickname: '')
user.valid?
expect(user.errors[:nickname]).to include("can't be blank")
end
end
context '許可される文字の場合' do
context '英大文字小文字数字#$%&()-._' do
it 'エラーが出ないこと' do
user = User.new(nickname: 'ARZatz809(_#-$%.&)')
user.valid?
expect(user.errors[:nickname]).to be_blank
end
end
end
context '許可されない文字の場合' do
context '許可されていない文字"?"が含まれている場合' do
it 'エラーが出ること' do
user = User.new(nickname: 'correct?')
user.valid?
expect(user.errors[:nickname]).to include('には半角英数字と#$%&()-._のみ使用できます。')
end
end
end
end
end
これを綺麗にすると以下のようになります。(参考:
使えるRSpec入門・その1「RSpecの基本的な構文や便利な機能を理解する」 - Qiita
)
require 'rails_helper'
RSpec.describe User, type: :model do
describe '#nickname' do
subject { user.errors[:nickname] }
let(:user) { User.new(params) }
let(:params) { {nickname: nickname} }
before do
user.valid?
end
context '空白のとき'do
let(:nickname) { '' }
it { is_expected.to include("can't be blank") }
end
context '許可される文字の場合' do
context '英大文字小文字数字#$%&()-._' do
let(:nickname) { 'ARZatz809(_#-$%.&)' }
it { is_expected.to be_blank }
end
end
context '許可されない文字の場合' do
context '許可されていない文字"?"が含まれている場合' do
let(:nickname) { 'correct?' }
it { is_expected.to include('には半角英数字と#$%&()-._のみ使用できます。') }
end
end
end
end
繰り返しがなくなってすっきりしました。
ここでふと思いました。
このテストコード、対象のエラーが含まれることはチェックできるけど、想定外のエラーが(間違って)含まれることはテストできていないじゃん、と。
ここでの方針としては、
- includeでなく配列同士の比較を行う
- エラーの数をチェックする
などが思いつきます。今回は
方法にします。この方法をとることで、
- エラーの順番は問わず
- 想定外のエラーが間違って入っていることを防ぐ
ことができます。
さて、テストの対象はsubject
に書かれています。これのサイズを取得したい。
これにはits
を使用します。
RSpec3からits
はgemに分離されているのでインストールします。
Gemfile
group :development, :test do
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
gem 'rspec-rails'
gem 'rspec-its'
end
bundle installします。
テストを追加します。
its(:size) { is_expected.to eq 1 }
のように書くとuser.errors[:nickname].size
が1かどうかをテストすることができます。
RSpec.describe User, type: :model do
describe '#nickname' do
subject {user.errors[:nickname]}
context '空白のとき'do
let(:nickname) { '' }
it { is_expected.to include("can't be blank") }
its(:size) { is_expected.to eq 1 }
end
context '許可される文字の場合' do
context '英大文字小文字数字#$%&()-._' do
let(:nickname) {'ARZatz809(_#-$%.&)'}
it { is_expected.to be_blank}
end
end
context '許可されない文字の場合' do
context '許可されていない文字"?"が含まれている場合' do
let(:nickname) {'correct?'}
it { is_expected.to include('には半角英数字と#$%&()-._のみ使用できます。')}
its(:size) { is_expected.to eq 1 }
end
end
end
end
以上でsubjectに指定した配列のサイズ(長さ)をテストすることができました。
環境
参考