3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Ruby on Rails】Rspec・rails-controller-testingを用いたテスト実施方法

Posted at

ここではGemファイルのRspec、rails-controller-testingを用いた
テストの大まかな流れを記載しています。

前提
【開発環境】
・Rails7
・Docker(DockerファイルにてGemのbundle installが行われるように設定済)

目次
・テストで使用するGem(RSpecとrails-controller-testing)をインストール
・コントローラー&モデルのテストで使用するファイルを作成
・テスト用のDB作成(必要な場合)
・テストの実行(モデルの場合)
・テストの実行(コントローラーの場合)

【テストで使用するGem(RSpecとrails-controller-testing)をインストール】

1 Gemfileを開きdevelopmentのテスト環境のブロックへrspec-railsを追記する。

rspec-railsのバージョンが古いと、scopeエラーが発生することがあるので、できるだけ最新をとってくるようにする。(これで結構はまっていました…)

Gemfile
group :development, :test do
  # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
  gem "rspec-rails", "~> 4.0.2"
  gem 'rails-controller-testing'
  gem "debug", platforms: %i[ mri mingw x64_mingw ]
end

2 ターミナルでbuildコマンドを実行し、Gemをインストールする

terminal
docker-compose build

3 rspecの設定ファイルを生成する

terminal
docker-compose run web bundle exec rails g rspec:install

specフォルダ配下に以下が生成されていれば良い
spec/spec_helper.rb
spec/rails_helper.rb


【コントローラー&モデルのテストで使用するファイルを作成】

1 まずははじめにrailsのコンテナを起動する

terminal
# railsコンテナ立ち上げ
docker-compose up
terminal
# 起動しているかどうかの確認
docker-compose ps

起動しているかどうかの確認時に、「State」がupになっていれば良い

2 ユーザーモデルのテストを記載するファイルを作成する

terminal
docker-compose exec web bundle exec rails g rspec:model User

specフォルダ配下に以下が生成されていれば良い
spec/models/user_spec.rb

user_spec.rbのデフォルトの内容は以下

user_spec.rb
    RSpec.discribe User, type: :model do
    # ペンディングはデフォルトで記載されている(削除してよい)
        pending "add some examples to (or delete) #{__FILE__}"
    end

4 ユーザーコントローラーのテストを記載するファイルを作成する

terminal
    docker-compose exec web bundle exec rails g rspec:controller Users

specフォルダ配下に以下が生成されていれば良い
spec/controllers/users_controller_spec.rb

users_controller_spec.rbのデフォルトの内容は以下

users_controller_spec.rb
    RSpec.describe UsersController, type: :controller do
    
    end

【テスト用のDB作成(必要な場合)】

1 テスト用のDBを作成する

DB作成コマンドを実行する

terminal
docker-compose exec web bundle exec rails db:create

Railsでテストを実行する場合は、デフォルトでtestという環境で動作し、
DBもテスト用のものが使用される

【テストの実行(モデルの場合)】

terminal
# モデルのテスト実行コマンド
docker-compose exec web bundle exec rspec ./spec/models/
terminal(結果例)
# example:実行したテスト failures:失敗したテスト pending:保留しているテスト
1 example, 0 failures, 1 pending

【メソッドの定義(テスト駆動開発)】

テスト駆動開発
…一度間違ったメソッドを定義して、テスト実行する

定義内容例
まずはモデルで「年齢」を定義する

app/models/user.rb
class User < ApplicationRecord
    def age
        0
    end
end

次にスペックファイルを記載する

spec/models/user_spec.rb
    reqire 'rails_helper'
    
    RSpec.discribe User, type: :model do
    
        # 何をテストするのかのテストの対象を記載(一般的には#メソッド名)
        describe '#age' do
        
            # どういう条件下で行うテストであるかを書く
            context '5年前の生年月日の場合' do
            
                # 上記contextが表すユーザーを定義
                let(:user){User.new(birthday: Time.zone.now - 5.years) }
                
                # 最終的にどういう状況であるのが正しいのかをテストする
                it '年齢が5歳であること' do
                
                    # expectの中にはテスト対象とするメソッドの呼び出しなどを記載する
                    # 'eq'等の記載はマッチャーと呼ぶ(検索するときはexpect マッチャーと記載する)
                    expect(user.age).to eq 5
                end
            end
        end
    end
    
    # ペンディングは削除する
    #   pending "add some examples to (or delete) #{__FILE__}"
    end

この状態でテスト実行する

terminal
# モデルのテスト実行コマンド
docker-compose exec web bundle exec rspec ./spec/models/

app/models/user.rbで定義された値が0であり、
5ではないため以下のような結果が返ってくる

terminal(結果例)
# example:実行したテスト failures:失敗したテスト pending:保留しているテスト
1 example, 1 failure

【メソッドの定義(正しく動作する場合)①】

まず生年月日から年齢を取得できるようにモデル側で定義する

app/models/user.rb
class User < ApplicationRecord
    def age
        # 現在の日本時間
        now = Time.zone.now
        
        # 現在の日付と誕生日の日付をint型に直し、現在の日付 - 誕生日の日付を表す
        # 結果を10000で割ることで年数を取得している
        #(日付を引き算した年数の部分のみを取得して月以下の部分を切り捨てるために10000としている)→5桁目から上の部分を取得している
        (now.strftime('%Y%m%d')).to_i - birthday.strftime('%Y%m%d').to_i) / 10000
    end
end

テストの実行

terminal
# モデルのテスト実行コマンド
docker-compose exec web bundle exec rspec ./spec/models/
terminal(結果例)
# example:実行したテスト failures:失敗したテスト pending:保留しているテスト
1 example, 0 failure

【メソッドの定義(正しく動作する場合)②】

境界値で確認するためにモックを準備する

モック
…テスト用にダミーのオブジェクトを用意したり、
 特定のメソッドを選んだ場合に決まった値を返すように設定することができる。

app/models/user.rb

   # berforeブロック内でtimezoneなどの挙動を設定することができる
   before do
     allow(Time.zone).to receive(:now).and_return(Time.zone.parse('2024/04/01'))
   end

   context '5年前の生年月日の場合' do
           
       # 上記contextが表すユーザーを定義
       let(:user){User.new(birthday: Time.zone.now - 5.years) }
               
       # 最終的にどういう状況であるのが正しいのかをテストする
       it '年齢が5歳であること' do    
       
           # expectの中にはテスト対象とするメソッドの呼び出しなどを記載する
           # 'eq'等の記載はマッチャーと呼ぶ(検索するときはexpect マッチャーと記載する)
           expect(user.age).to eq 5
       end
   end
   
   context '5年前に生まれてちょうど誕生日の場合' do
     let(:user) {User.new(birthday: Time.zone.parse('2019/04/01')) }
     it '年齢が5歳であること' do
       expect(user.age).to eq 5
     end
   end
   context '5年前に生まれて誕生日が来ていない場合' do
     let(:user) {User.new(birthday: Time.zone.parse('2019/04/02')) }
     it '年齢が4歳であること' do
       expect(user.age).to eq 4
     end
   end
  

テストの実行

terminal
# モデルのテスト実行コマンド(ドキュメント形式でテスト結果を表示できるオプション(-f)付き)
docker-compose exec web bundle exec rspec -f d ./spec/models/

テスト実施結果(例)

terminal
User
  #age
    5年前の生年月日の場合
      年齢が5歳であること
    5年前に生まれてちょうど誕生日の場合
      年齢が5歳であること
    5年前に生まれて誕生日が来ていない場合
      年齢が4歳であること

Finished in 0.11773 seconds (files took 5.81 seconds to load)
3 examples, 0 failures

このようにモデルの動作が正しいかどうかの確認を行うことができる。

【テストの実行(コントローラーの場合)】

ジェネレーターコマンドで作成しておいたコントローラーに以下を記載する。

spec\controllers\users_controller_spec.rb
require 'rails_helper'

RSpec.describe UsersController, type: :controller do

    describe 'GET #new' do
        # beforeブロックではこのコントローラーアクションにGETのHTTPメソッドで擬似的にアクセスしている
        # これによってGETのリクエスト結果がresponseという変数に格納される
        before { get :new }

        it 'レスポンスコードが200であること' do
            expect(response).to have_http_status(:ok)
        end

        it 'newテンプレートをレンダリングすること' do
            expect(response).to render_template :new
        end

        it '新しいuserオブジェクトがビューに渡されること' do
            expect(assigns(:user)).to be_a_new(User)
        end
    end
end

テストの実行

terminal
# コントローラーのテスト実行コマンド(ドキュメント形式でテスト結果を表示できるオプション(-f)付き)
docker-compose exec web bundle exec rspec -f d ./spec/controllers/

テスト実施結果(例)

terminal
UsersController
  GET #new
    レスポンスコードが200であること
    newテンプレートをレンダリングすること
    新しいuserオブジェクトがビューに渡されること

Finished in 3.02 seconds (files took 5.69 seconds to load)
3 examples, 0 failures

このようにコントローラーが正しく動作しているかどうかを確認することができる。

3
0
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
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?