22
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Ruby on Rails】RSpecでのモデルテスト

Posted at

開発環境

ruby 2.5.7
Rails 5.2.4.3
OS: macOS Catalina

前提

【Ruby on Rails】RSpec導入まで
こちらが出来ている前提で進めます。

modelのテスト準備

##・バリデーションの設定
今回はタイトルカラムがあるかどうかと文字数のテストします。

app/models/post.rb
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ファイルを作成し、下記のように記述します。

spec/support/factory_bot.rb
RSpec.configure do |config|
  config.include FactoryBot::Syntax::Methods
end

その後、下記を追加します。

spec/rails_helper.rb
# 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' # <ーーー 追加

...

実際のコード

まずはダミーデータを作成します。

spec/factories/user.rb
FactoryBot.define do
  factory :user do
    email { Faker::Internet.email }
    phone_number { 12345678909 }
    password { 'password' }
    password_confirmation { 'password' }
  end
end
spec/factories/post.rb
FactoryBot.define do
  factory :post do
    body { Faker::Lorem.characters(number:20) }
    user
  end
end

次にテストコードを記述します。

spec/models/post_spec.rb
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

22
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?