開発環境
ruby 2.5.7
Rails 5.2.4.3
OS: macOS Catalina
前提
【Ruby on Rails】RSpec導入まで
こちらが出来ている前提で進めます。
modelのテスト準備
##・バリデーションの設定
今回はタイトルカラムがあるかどうかと文字数のテストします。
class Post < ApplicationRecord
belongs_to :user
validates :title, presence: true, length: {maximum: 20}
end
##・ファイルの作成
①
spec配下にmodelsフォルダとfactoriesフォルダを作成し、
テストしたいモデルのファイルも作成します。
今回はpostモデルをテストします。
またユーザーがログインしている状態でしか投稿できないようにするために、
useモデルも作成します。
ファイル構成は下記の状態です。
spec/models/post_spec.rb
→テストしたい内容を記述します
spec/factories/post.rb
spec/factories/user.rb
→ダミーデータを作成します
②
FactoryBotを使えるようにします。
使用するとuser = create(:user) のようにDB登録やモデルのビルドができるため便利です。
spec配下にsupportフォルダとfactory_bot.rbファイルを作成し、下記のように記述します。
RSpec.configure do |config|
config.include FactoryBot::Syntax::Methods
end
その後、下記を追加します。
# This file is copied to spec/ when you run 'rails generate rspec:install'
require 'spec_helper'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../config/environment', __dir__)
# Prevent database truncation if the environment is production
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'rspec/rails'
require 'support/factory_bot' # <ーーー 追加
...
実際のコード
まずはダミーデータを作成します。
FactoryBot.define do
factory :user do
email { Faker::Internet.email }
phone_number { 12345678909 }
password { 'password' }
password_confirmation { 'password' }
end
end
FactoryBot.define do
factory :post do
body { Faker::Lorem.characters(number:20) }
user
end
end
次にテストコードを記述します。
require 'rails_helper'
RSpec.describe 'Postモデルのテスト', type: :model do
describe 'バリデーションのテスト' do
# factoriesで作成したダミーデータを使用します。
let(:user) { FactoryBot.create(:user) }
let!(:post) { build(:post, user_id: user.id) }
# test_postを作成し、空欄での登録ができるか確認します。
subject { test_post.valid? }
let(:test_post) { post }
context 'titleカラム' do
it '空欄でないこと' do
test_post.title = ''
is_expected.to eq false;
end
it '20文字以下であること' do
post.title = Faker::Lorem.characters(number:21)
expect(post.valid?).to eq false;
end
end
end
describe 'アソシエーションのテスト' do
context 'customerモデルとの関係' do
it 'N:1となっている' do
expect(Post.reflect_on_association(:user).macro).to eq :belongs_to
end
end
# has_manyの関係性で記述するのもありです。
# context 'PostCommentモデルとの関係' do
# it '1:Nとなっている' do
# expect(Post.reflect_on_association(:post_comments).macro).to eq :has_many
# end
# end
end
end
その後、ターミナルで下記を実行してください。
$ rspec spec/models
テストを通過すると
Finished in 0.52408 seconds (files took 2.11 seconds to load)
3 examples, 0 failures
このように表示されるためテスト内容が正しいことを表しています。
逆にテストを通過しない場合、このような形でどこでエラーが起きているかわかるので、
テストコードが間違っているのか、バリデーションが間違っているかなどがわかるようになります。
Failures:
1) Postモデルのテスト バリデーションのテスト titleカラム 20文字以下であること
Failure/Error: let!(:post) { build(:post) }
NoMethodError:
undefined method `build' for #<RSpec::ExampleGroups::Post::Nested::Title:0x000000000619e938>
# ./spec/models/post_spec.rb:9:in `block (3 levels) in <top (required)>'
2) Postモデルのテスト バリデーションのテスト titleカラム 空欄でないこと
Failure/Error: let!(:post) { build(:post) }
NoMethodError:
undefined method `build' for #<RSpec::ExampleGroups::Post::Nested::Title:0x0000000007491518>
# ./spec/models/post_spec.rb:9:in `block (3 levels) in <top (required)>'
Finished in 0.07992 seconds (files took 2.41 seconds to load)
2 examples, 2 failures
Failed examples:
rspec ./spec/models/post_spec.rb:11 # Postモデルのテスト バリデーションのテスト titleカラム 20文字以下であること
rspec ./spec/models/post_spec.rb:15 # Postモデルのテスト バリデーションのテスト titleカラム 空欄でないこと
また下部にあるrspec ./spec/models/post_spec.rb:11を使い、
下記のように個別にテスト内容を確認することも出来ます。
$ rspec spec/models/post_spec.rb:11
まとめ
今回は
1,空白での登録を防ぐバリデーション presence: true
2,文字数制限のバリデーション length: {maximum: 20}
3,リレーションの関係性の確認 belongs_to :user
上記をテストしましたが、この他にも色々テスト方法があるため、
興味のある方は調べてみてください。
またtwitterではQiitaにはアップしていない技術や考え方もアップしていますので、
よければフォローして頂けると嬉しいです。
詳しくはこちら https://twitter.com/japwork