Rails チュートリアルを勉強中のみなさま、こんにちは!
突然ですが、テストって、難しくないですか?
第3章に突如として現れ、詳しい説明もなく、テストが始まり、
最後の14章までに、non stop でテストがたくさん出てきる・・・
テストが重要なのはわかったけど!
これって、初心者にはハードル高くないですか???
私は、何度となく挫折しかけました汗
この記事が、少しでもテストに対する抵抗感が減るきっかけになれば、幸いです。
1. テストの種類について
Rails チュートリアルを進めていくと、
integration test っていうのが出てきます。
普通のテストとどう違うんだ!
使い分けがわからなくなりますよね。(自分だけでしょうか)
テストは一般的に、3つに分かれます。
テスト名 | 概要 |
---|---|
単体テスト | モデルやビューヘルパー単体の動作をチェック |
機能テスト | コントローラー/ビューの呼び出し結果をチェック |
統合テスト | ユーザーの実際の操作を想定し、複数のコントローラーにまたがるアプリの挙動をチェックする |
それぞれ、詳しくみていきましょう
## 単体テスト
Rails で行うテストの中で、最も基本的なテスト。
アプリを構成するライブラリ(主にモデル)が、正しく動作するかをチェックします。
Rails チュートリアル 第6章 リスト6.5
require 'test_helper'
class UserTest < ActiveSupport::TestCase
def setup
@user = User.new(name: "Example User", email: "user@example.com")
end
test "should be valid" do
assert @user.valid?
end
end
assert メソッドは、第1引数がtrue である場合に、テストが成功したものとみなします。
setup メソッドで、テストが走る前に、インスタンス変数の @user を宣言し、valid?メソッドで有効性を確認しているわけですね。
assertメソッドにはそれ以外にも、
assert_not, assert_equal, assert_match などなど
数多くあるので、気になる方は、こちらをご参照ください。
##機能テスト
コントローラーの動作や、ビューの出力をチェックするためのテスト。
HTTPリクエストを擬似的に作成することで、アクションメソッドを実行し、HTTPステータスやテンプレート変数、最終的な出力の構造までを確認する。また、ルーティングもチェックします。
コントローラって、アプリが受け付けたWebリクエストを処理して
レンダリングされたビューを返しますよね。
機能テストでは、コントローラーのアクションが、リクエストや期待される結果(レスポンス、場合によってはHTMLビュー)をどう扱っているかをテストします。
つまり、以下のことを行うんです。
・Webリクエストが成功したか
・正しいページにリダイレクトされたか
・ユーザー認証が成功したか
・レスポンスのテンプレートに正しいオブジェクトが保存されたか
・ビューに表示されたメッセージは適切か
実際のコードを見てみましょう。
Rails チュートリアル第7章 リスト7.23 をご参照ください。
class UsersController < ApplicationController
.
.
.
def create
@user = User.new(user_params)
if @user.save
else
render 'new'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
end
require 'test_helper'
class UsersSignupTest < ActionDispatch::IntegrationTest
test "invalid signup information" do
get signup_path
assert_no_difference 'User.count' do
post users_path, params: { user: { name: "",
email: "user@invalid",
password: "foo",
password_confirmation: "bar" } }
end
assert_template 'users/new'
end
end
❶ get メソッドでリクエストを生成する。
まず、コントローラーを起動するために、getメソッドで、擬似的にHTTPリクエストを生成します。
get メソッド
get path, opts
path: リクエスト先のパス opts: 動作オプション (params, xhr, headersなど)
その他のHTTPメソッド(post, delete, patchなど)も、同じ構文となります。
このコードでは、引数 paramsを使用していますね。
params は、ハッシュ形式で、{キー: 値} と書きます。
❷ assertメソッド
この機能テストでは、単体テストで使用できたassertメソッド に加え、次のような
assertメソッドを使用できます。
メソッド | 概要 |
---|---|
assert_difference (exp [.diff [,msg]]){block} | ブロック配下の処理を実行した前後で、式 expの値が引数 diffだけ変化しているか |
assert_no_difference (exp [,msg]){block} | ブロック配下の処理を実行した前後で式 expの値が変化しないか |
assert_response (type [,msg]) | 指定されたHTTPステータスが返されたか。:success(200)、:redirect(300番台)、:missing(404)、:error(500番台)など |
assert_redirected_to ([opts [,msg]]) | リダイレクト先 optsが正しいか |
assert_template (temp [,msg]) | 指定されたテンプレートが選択されたか |
assert_select (selector [, equality [,msg]]) | selectorに合致した要素の内容を引数equalityでチェック |
Rails チュートリアルに、いっぱい出てきましたよね、これら・・・。 中でも、1つ個人的につまずいた、assert メソッドを抜粋します。
assert_select 'a[href=?]', about_path
これは、about_path に合致するリンクが存在するかどうかを、確認しているものです。 この? が途中から、意味不明に見えてきたのですが、Railsチュートリアル リスト5.32に ちゃんと説明が書いてありました。 > Railsは、自動的にはてなマーク "?" を about_pathに置換しています。 これにより、次のようなHTMLがあるかどうかをチェックすることができます。 \...\
なるほど納得ですね〜
統合テスト
これは、複数のコントローラーにまたがって、ユーザーの実際の操作を追跡する
用途で利用するテスト。
早速実際のコードを見てみましょう。
Rails チュートリアル 第5章 リスト5.32
require 'test_helper'
class SiteLayoutTest < ActionDispatch::IntegrationTest
test "layout links" do
get root_path
assert_template 'static_pages/home'
assert_select "a[href=?]", root_path, count: 2
assert_select "a[href=?]", help_path
assert_select "a[href=?]", about_path
assert_select "a[href=?]", contact_path
end
end
このコードは、今までの知識だけで理解できますね!
私がつまずいたのは、
follow redirect!
そんなに、力を込めて、redirect! するなよっていう気持ちでした.
Rails チュートリアル第8章 リスト8.23
require 'test_helper'
class UsersLoginTest < ActionDispatch::IntegrationTest
def setup
@user = users(:michael)
end
.
.
.
test "login with valid information" do
get login_path
post login_path, params: { session: { email: @user.email,
password: 'password' } }
assert_redirected_to @user
follow_redirect!
assert_template 'users/show'
assert_select "a[href=?]", login_path, count: 0
assert_select "a[href=?]", logout_path
assert_select "a[href=?]", user_path(@user)
end
end
これ
この follow redirect!
なんで必要か?
よく探したら、Rails チュートリアル第7章に書いてありました。
このメソッドは、POSTリクエストを送信した結果を見て、指定されたリダイレクト先に移動するメソッドです。
あれ?これって、assert_redirected_to メソッドと
どう違うんだろうと思いませんか?
おそらくですが
assert _redirected_to は、駅員が、「お客さんこの駅へ向かう切符でよろしいですか?」
と確認すること
follow_redirect! は、 「その切符の行き先まで、実際に行くこと!」
の違いだと解釈しました。(違ってたら、コメントください。。)
なお、このテストの
assert_redirected_to @user
この書き方がよくわからない方。特に @user のとこ。
こちらの記事が最高にわかりやすかったので、初心者の方は、ぜひ読んでみてくださいね!
簡単にまとめますと、
redirect_to のあとは絶対パスが来る。
→ user_url(@user.id)
→ urlヘルパーと()は省略可能 → @user.id
→ モデルオブジェクト@user って書けば、Railsが自動的にid 探す
→ @userになる。
テストってかなり難しいと思います。
Railsチュートリアルを終わった今でも、かける自信はありません。
また、minitestの記事をググってもなかなか見つけることはできませんでした。
この記事は、今後もバージョンアップして、少しでも皆様のお役に立てれればと思います。
では、楽しいRails ライフを〜
参考文献:
Rails チュートリアル
Railsガイド
Ruby on Rails5 アプリケーションプログラミング