サポートモジュールを使って結合テストの可読性を向上させる方法


概要

サポートモジュール導入の方法についての記事です。

導入の手順の全体像

①サポートモジュール用のディレクトリとファイルを手動で作成
②サポートモジュールの内容を記述
③サポートモジュールを読み込めるようにする
④結合テストコードを編集

①サポートモジュール用のディレクトリとファイルを手動で作成

specディレクトリ配下にsupportディレクトリを作成し、その配下に〜_support.rbを作成します。(〜の部分は任意)

②サポートモジュールの内容を記述

(例)投稿における記述をモジュール化しています。

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

③サポートモジュールを読み込めるようにする

ir[Rails.root.join('spec', 'support', '*', '.rb')].sort.each { |f| require f }という記述のコメントアウトを外して、読み込まれるようにします。

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'
# Add additional requires below this line. Rails is not loaded until this point!

# Requires supporting ruby files with custom matchers and macros, etc, in
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
# run as spec files by default. This means that files in spec/support that end
# in _spec.rb will both be required and run as specs, causing the specs to be
# run twice. It is recommended that you do not name files matching this glob to
# end with _spec.rb. You can configure this pattern with the --pattern
# option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
#
# The following line is provided for convenience purposes. It has the downside
# of increasing the boot-up time by auto-requiring all files in the support
# directory. Alternatively, in the individual `*_spec.rb` files, manually
# require only the support files necessary.
#
Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f }

続いて、同じファイルのRSpec.configureの中に、以下のようにモジュール名を明記します。

spec/rails_helper.rb
RSpec.configure do |config|
  config.include SignInSupport
  config.include DefinitionUpSupport
  config.include ReviewUpSupport
  config.include PageUpSupport
# 順次追記していきます

④結合テストコードを編集

以下のように記述を置き換え、重複したコードをまとめて書くことで、可読性を向上させます。

spec/system/definitions_spec.rb
require 'rails_helper'

RSpec.describe "Definitions", type: :system do
  before do
    @user = FactoryBot.create(:user)
    @definition_title = Faker::Lorem.sentence
    @definition_body = Faker::Lorem.sentence
  end
  context '投稿ができるとき'do
    it 'ログインしたユーザーは新規投稿できる' do
    # ログインする
    sign_in(@user)

    # 新規投稿する
    definition_up(@definition_title, @definition_body)

    # トップページに遷移する
    visit root_path

    # トップページには先ほど投稿した内容の投稿が存在することを確認する
    expect(page).to have_content(@definition_title)
    end
  end
  context '投稿ができないとき'do
    it 'ログインしていないと新規投稿ページに遷移できない' do
       # トップページに遷移する
       visit root_path

       # 新規投稿ページへのリンクがない
       expect(page).to have_no_content('投稿')
    end
  end
end

サポートモジュールとは

メソッド等をまとめる機能のこと(RSpecに搭載)

メソッドとして処理をまとめることができ、複数回使うメソッドを定義しています。

spec/rails_helper.rbでコメントアウトする意味

正しRSpec内では共通化した部分を呼び起こすのに制限がある。制限を取っ払う必要があります。

ここでは、ルーティングを拡張する設定をしている。specディレクトリの中の、supportディレクトリの中の、**(全てのファイル)の中の、.rbだけついた全部のファイルが対象となっています。

左から右にいくにつれてファイルが奥深くなっていくイメージです。

spec/rails_helper.rbについて

configファイルでSignSupportを設定に含めて、ファイルを拡張しているという設定をしております。ファイルに関して拡張した内容を記述しているということです。

同じ処理を繰り返す時に1個にまとめる際にサポートモジュールを使用します。
Railsの理念として繰り返し同じ記述をしてならないルールがあるためです。

以上です。