Rails6】RSpecによるページネーション機能(kaminari)の結合テストの実装


はじめに

サービスの品質を保つために必要不可欠なテストを実施しております。

今回は、kaminariを使用して、実装したページネーション機能の結合テストを実装し、その実装内容を記事にしていきたいと思います。

前提

・kaminariというgemを使ってのページネーション機能は実施済み

gem 'kaminari'
gem 'kaminari-bootstrap'

・投稿時の結合テストと同じ、テストファイルにページネーション機能の内容も記述しています。
 投稿時におけるテストコードの記述は以下のURLよりご覧になれます。

バージョン

rubyのバージョン ruby-2.6.5
Railsのバージョン Rails:6.0.0
rspec-rails 4.0.0

実施したテスト

ページネーションの画面

モデルにてページネーションの設定

モデルにて、投稿の表示は1ページ3件までとしています。

app/models/definition.rb
# 〜省略〜

# 最近作成されたユーザーから表示
default_scope -> { order(created_at: :desc) }
# 一度に表示する投稿数
paginates_per 3

# 〜省略〜

definitionsテーブルのカラムの紹介

xxx_create_definitions.rb
class CreateDefinitions < ActiveRecord::Migration[6.0]
  def change
    create_table :definitions do |t|
      t.text       :title,          null: false
      t.text       :body,           null: false
      t.references :user,           foreign_key: true
      t.timestamps
    end
  end
end

モデル内のバリデーション

app/models/definition.rb
class Definition < ApplicationRecord
  belongs_to :user
  has_many :answers, dependent: :destroy
  has_many :reviews, dependent: :destroy
  has_many :notifications, dependent: :destroy
  has_many :likes, dependent: :destroy

  validates :title, presence: true
  validates :body, presence: true

# 〜省略〜

FactoryBotの内訳

spec/factories/definitions.rb
FactoryBot.define do
  factory :definition do
    title                        {Faker::Lorem.sentence}
    body                         {Faker::Lorem.sentence}
    association :user
  end
end

サポートモジュール

新規投稿する際の記述をモジュール化しています。

spec/support/definition_up_support.rb
module DefinitionUpSupport
  def definition_up(definition_title, definition_body)

    # 新規投稿ページへのリンクがあることを確認する
    expect(page).to have_content('投稿')

    # 投稿作成ページに移動する
    visit new_definition_path

    # フォームに情報を入力する
    fill_in 'definition[title]', with: definition_title
    fill_in 'definition[body]', with: definition_body

    # 送信するとDefinitionモデルのカウントが1上がることを確認する
    expect{
      find('input[name="commit"]').click
    }.to change { Definition.count }.by(1)

    # 投稿完了ページに遷移することを確認する
    expect(current_path).to eq(root_path)
  end
end

ページ遷移して投稿の存在を確認する記述をモジュール化しています。

spec/support/page_up_support.rb
module PageUpSupport
  def page_up(definition)
    # ページ遷移していることを確認する
    expect(current_path).to eq(root_path)

    # 投稿があることを確認する
    expect(page).to have_no_content("#{definition.title}")
  end
end

テストコードの内容

spec/system/definitions_spec.rb

#投稿における結合テストの記述は省略

RSpec.describe 'ページネーションについて', type: :system do
    before do
      @definition = FactoryBot.create(:definition)
      @definition_title = Faker::Lorem.sentence
      @definition_body = Faker::Lorem.sentence
    end
      context 'ページネーションでページ遷移ができるとき' do
          it 'ログインしたユーザーはページネーションでページ遷移ができる' do
          # definitionを投稿したユーザーでログインする
          sign_in(@definition.user)

          # ①新規投稿する(投稿は3件表示のため4つ投稿を行う)
          definition_up(@definition_title, @definition_body)

          # ②新規投稿する(投稿は3件表示のため4つ投稿を行う)
          definition_up(@definition_title, @definition_body)

          # ③新規投稿する(投稿は3件表示のため4つ投稿を行う)
          definition_up(@definition_title, @definition_body)

          # ④新規投稿する(投稿は3件表示のため4つ投稿を行う)
          definition_up(@definition_title, @definition_body)

          # 投稿ページに移動する
          visit root_path(anchor:"ethics")

          # ページがあることを確認
          expect(page).to have_css(".page-link")

          # ページネーション'2'のボタンをクリックし、次ページへと行く
          expect{ find_link('2', rel="next").click }

          # ページ遷移していることを確認し、投稿があることを確認する
          page_up(@definition)

          # ページネーション'1'のボタンをクリックし前ページへと行く
          expect{ find_link('1', rel="prev").click }

          # ページ遷移していることを確認し、投稿があることを確認する
          page_up(@definition)

          # ページネーションボタン'最後'のボタンをクリックし、最後のページへと行く
          expect{ find_link('最後', ".page-link").click }

          # ページ遷移していることを確認し、投稿があることを確認する
          page_up(@definition)

          # ページネーションボタン'最初'のボタンをクリックし、最初のページへと行く
          expect{ find_link('最初', ".page-link").click }

          # ページ遷移していることを確認し、投稿があることを確認する
          page_up(@definition)
       end
    end
end

以上です。