Help us understand the problem. What is going on with this article?

railsのテストディレクトリ構造とテスト処理

railsのテストディレクトリ

テストとは開発をしながら、動作するかテストすること。テストディレクトリにはテストに必要なファイルがある。

models(モデルテスト)

モデル名test.rbに記述するテスト。(例 test/models/usertest.rb)

rails g model ~でモデルが作られると
testディレクトリにそのモデルのためのテストができる

書き方
まずモデルのインスタンスを作成する(主にseup関数で行う)

そのインスタンスが機能しているかや、複数のインスタンスの関係性が機能しているかなど確認する。

test/models/user_test.rb
require 'test_helper'

class UserTest < ActiveSupport::TestCase

  def setup #インスタンス作成
    @user = User.new(name: "Example User", email: "user@example.com")
  end

  test "name should be present" do
    @user.name = "     "
    assert_not @user.valid? #このテストの場合Userファイルで書いたvalidateが発動しているかテストしている
  end
end

controllers(コントローラーテスト)

controller_test.rbに記述するテスト。

rails g controller ~でコントローラーが作られると
testディレクトリにそのコントローラーのためのテストができる

書き方
まず必要な処理をsetupで書く

どのアクションを発動させるためにどのURLを発信するかを書き、assert関数でテスト内容を書く。
integration testとの違いは一つのアクション内で完結するテストということ。

test/controllers/users_controller_test.rb
require 'test_helper'

class UsersControllerTest < ActionDispatch::IntegrationTest

  def setup
  
  
  end

  test "should get new" do
    get users_new_url
    assert_response :success
  end
end

integration(統合テスト)

test/integration/統合テスト名_test.rbに記述するテスト。

rails g integration_test 〜でtestディレクトリに作られる。

書き方
まず必要な処理をsetupで書く

どのアクションを発動させるためにどのURLへ発信するかを書き、assert関数でテスト内容を書く
様々なURLへ発信して、如何にも実際に手で動かしているテストのように行う。

test/integration/microposts_interface_test.rb
require 'test_helper'

class MicropostsInterfaceTest < ActionDispatch::IntegrationTest

  def setup
  
  
  end

  test "micropost interface" do
  get root_path
  assert ...
  
  
  post microposts_path ...
  assert ...
  
  
  end

機能テストとの違いは一つのコントローラーのアクション内でのテストではなく、rootingを通して様々なコントローラーに繋いでどうなるかなどをテストする

mailer(メールテスト)

メーラーを作成すると自動で以下のファイルが作成される。

・preview
これはメールの内容を視覚的にブラウザで確認するためにある

# Preview this email at http://localhost:3000/rails/mailers/user_mailer/account_activation
  def account_activation
    user = User.first
    user.activation_token = User.new_token
    UserMailer.account_activation(user)
  end
#これはhttp://localhost:3000/rails/mailers/user_mailer/account_activationにアクセスするとpreviewのaccount_activationが発動し、
#UserMailer.account_activation(user)の結果を確認できるってこと

・mailerテスト
メール内容に特定の要素は存在するかなどを確認する

helpers(単体テスト)

上記のテストでは実施しにくいテストを行う。上記のテストより細部に関するテストと言える。app内で定義した関数処理がうまく作動しているかなどを確認する。
以下の例ではfull_title関数が正常に動作している確認している、

  test "full title helper" do
    assert_equal full_title, "Ruby on Rails Tutorial Sample App"
    assert_equal full_title("Help"), "Help | Ruby on Rails Tutorial Sample App"
  end

fixtures

テストで使うためのデータベースにあるデータとして記述される。ymlファイルに記述

test_helper.rb

全てのtestはtest_helper.rbを導入している。test_helper.rbの中にはtestで使う関数を書いている。
またappで使用している関数(app/helpersで定義されている)をtest環境でも使用したい場面がある。そんな時はapp/helpersにある関数定義ファイルをtest_helper.rbにincludeすることがある。

補足

setup関数

テストファイルのsetup関数で変数を作り、テスト内で採用する。

test/controllers/static_pages_controller_test.rb
require 'test_helper'

class StaticPagesControllerTest < ActionDispatch::IntegrationTest

  def setup
    @base_title = "Ruby on Rails Tutorial Sample App"
  end

  test "should get home" do
    get static_pages_home_url
    assert_response :success
    assert_select "title", "Home | #{@base_title}"
  end
データ変更後、データの値チェックをしたい時(reload)

テストの中でデータ変更を行った場合、reloadでデータ更新をしてから、値チェックをする。

 test "password reload" do
    log_in_as(@other_user)
    patch user_path(@other_user), params: {
                                    user: { password:              @other_user.password,
                                            password_confirmation: @other_user.password}}
    assert_not @other_user.reload.password #patchでデータ送信、更新後にインスタンスの中身を見たい時はreloadをしないといけない
  end
テストで作ったインスタンス変数の値を知りたい時(assigns)

controllerのアクション内で作成されたインスタンス変数のプロパティーの値を、テスト内で確認したい時、assigns()を使用する。assigns(インスタンス変数).データカラムとすることで確認できる。

controller
  def create
    @user = User.find_by(email: params[:email]
  end
test
  def "create test" do
    .
    .
    user = assigns(:user) 
    #@userというインスタンスが存在すれば、assigns(:user)でインスタンスのデータにアクセスできる。assigns(@user)ではだめ
    .
    .
  end
自動テスト

開発と同時並行で自動でテストする方法がある。開発で変更を加えるたびに自動でテストを行ってくれる。そのためわざわざテストコマンドを毎回打たなくて済む。

railsでは自動テストを導入するためにはGuardを取り入れる

Guard fileに自動テストするように指示を書く
詳しくはRuby on Rails チュートリアル

注意
Guardを使うときにspringという機能を使う
しかしspringがgitとの競合をしないように、.git ignoreファイルに、springを書きgitリポジトリに保存されないようにする

参考文献

Ruby on Rails チュートリアル
単体テスト・結合テスト・総合テストの違い、観点や注意点を簡単に説明する
Rails チュートリアル 【初心者向け】 テストを10分でおさらいしよう!

Tsuyozo
lifull
日本最大級の不動産・住宅情報サイト「LIFULL HOME'S」を始め、人々の生活に寄り添う様々な情報サービス事業を展開しています。
https://lifull.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away