記事概要
Ruby on Railsのモデル単体テストについて、まとめる
前提
- Ruby on Railsでアプリケーションを作成している
- アプリにRSpecをインストールしている
- RSpecの設定が完了している
RSpecとは
モデルテストコードを書く方針
インスタンスを生成し、それがモデルに規定したどおりの挙動になるか、を確かめる
例)バリデーションが正しく働くか
手順(テストファイル作成)
- モデルのテストファイルを生成するため、下記コマンドを実行する
# アプリのディレクトリに移動 % cd ~/[アプリ名] % rails g rspec:model [モデル名] -
spec/models/モデル名_spec.rbが作成されたことを確認する -
モデル名_spec.rbにrequire 'rails_helper'が記述されていることを確認するrequire 'rails_helper' RSpec.describe モデル名, type: :model do pending "add some examples to (or delete) #{__FILE__}" end - 上記から
pending "add some examples to (or delete) #{__FILE__}"を削除するrequire 'rails_helper' RSpec.describe モデル名, type: :model do end
手順(テスト用ダミー画像の用意)
-
publicディレクトリにimagesフォルダを手動作成する -
public/imagesフォルダに、ダミー画像を格納する
手順(テストケースの記述)
-
[モデル名]_spec.rbにテストケースを記述する
- 機能別・条件別・テスト詳細別にグループ分けを行う
- 保存するデータ(インスタンス)を作成する
- テストコードを記述する
※各テストコードが想定通りに実行できるかを確認するため、rails cコマンドでコンソールを起動して確認を行う
手順(テストファイルの実行)
- テストファイルを実行するため、下記コマンドを実行する
# アプリのディレクトリに移動 % cd ~/[アプリ名] % bundle exec rspec spec/models/モデル名_spec.rb - ターミナル.appで正常完了していることを確認する
結果が緑色で表示されれば実行成功
まとめ
画像添付した際にエラー発生
active_storageを用いたモデルの単体テストをする際に、エラーMySQL client is not connectedが発生した場合、下記を追記する
config/environments/test.rb
Rails.application.configure do
# MySQLのエラーが発生する場合、追記
config.active_job.queue_adapter = :inline
# 省略
end
devise(Gem)のデフォルトバリデーション
- emailが空では登録できない
- passwordが空では登録できない
- emailは@を含まないと登録できない
- 重複したemailが存在する場合は登録できない
- passwordとpassword_confirmationが不一致では登録できない
- passwordが5文字以下では登録できない
- passwordが129文字以上では登録できない
参考コード
他モデルと紐付けなし
require 'rails_helper'
RSpec.describe User, type: :model do
before do
@user = FactoryBot.build(:user)
end
describe 'ユーザー新規登録' do
context 'ユーザー登録できるとき' do
it 'nicknameとemail、passwordとpassword_confirmationが存在すれば登録できる' do
expect(@user).to be_valid
end
end
context 'ユーザー登録できないとき' do
it 'nicknameが空では登録できない' do
@user.nickname = ''
@user.valid?
expect(@user.errors.full_messages).to include("Nickname can't be blank")
end
it 'passwordとpassword_confirmationが不一致では登録できない' do
@user.password_confirmation = "#{@user.password_confirmation}123"
@user.valid?
expect(@user.errors.full_messages).to include("Password confirmation doesn't match Password")
end
it 'nicknameが7文字以上では登録できない' do
@user.nickname = 'aaaaaaa'
@user.valid?
expect(@user.errors.full_messages).to include('Nickname is too long (maximum is 6 characters)')
end
it '重複したemailが存在する場合は登録できない' do
@user.save
another_user = FactoryBot.build(:user)
another_user.email = @user.email
another_user.valid?
expect(another_user.errors.full_messages).to include('Email has already been taken')
end
it 'emailは@を含まないと登録できない' do
@user.email = 'testmail'
@user.valid?
expect(@user.errors.full_messages).to include('Email is invalid')
end
it 'passwordが5文字以下では登録できない' do
@user.password = '00000'
@user.password_confirmation = @user.password
@user.valid?
expect(@user.errors.full_messages).to include('Password is too short (minimum is 6 characters)')
end
it 'passwordが129文字以上では登録できない' do
@user.password = Faker::Internet.password(min_length: 129, max_length: 150)
@user.password_confirmation = @user.password
@user.valid?
expect(@user.errors.full_messages).to include("Password is too long (maximum is 128 characters)")
end
end
end
end
他モデルと紐付けあり+画像の紐付けあり
require 'rails_helper'
RSpec.describe Message, type: :model do
before do
@message = FactoryBot.build(:message)
end
describe 'メッセージ投稿' do
context 'メッセージが投稿できる場合' do
it 'contentとimageが存在していれば保存できる' do
expect(@message).to be_valid
end
it 'imageが空でも保存できる' do
@message.image = nil
expect(@message).to be_valid
end
end
context 'メッセージが投稿できない場合' do
it 'contentとimageが空では保存できない' do
@message.content = ''
@message.image = nil
@message.valid?
expect(@message.errors.full_messages).to include("Content can't be blank")
end
it 'userが紐付いていないと保存できない' do
@message.user = nil
@message.valid?
expect(@message.errors.full_messages).to include('User must exist')
end
end
end
end
Ruby on Railsまとめ