Rails チュートリアル　【初心者向け】　テストを10分でおさらいしよう！　


Rails チュートリアルを勉強中のみなさま、こんにちは！

突然ですが、テストって、難しくないですか？　

第3章に突如として現れ、詳しい説明もなく、テストが始まり、

最後の14章までに、non stop でテストがたくさん出てきる・・・　
　


テストが重要なのはわかったけど！
これって、初心者にはハードル高くないですか？？？　
<br>

私は、何度となく挫折しかけました汗
この記事が、少しでもテストに対する抵抗感が減るきっかけになれば、幸いです。　



# 1. テストの種類について


Rails チュートリアルを進めていくと、
integration test っていうのが出てきます。


普通のテストとどう違うんだ！
使い分けがわからなくなりますよね。(自分だけでしょうか)　

　
テストは一般的に、3つに分かれます。
<br>


|テスト名|概要|
|:---|:---|
|単体テスト|モデルやビューヘルパー単体の動作をチェック|
|機能テスト|コントローラー/ビューの呼び出し結果をチェック|
|統合テスト|ユーザーの実際の操作を想定し、複数のコントローラーにまたがるアプリの挙動をチェックする|

<br> 
それぞれ、詳しくみていきましょう　
<br>
## 単体テスト

Rails で行うテストの中で、最も基本的なテスト。
アプリを構成するライブラリ(主にモデル)が、正しく動作するかをチェックします。　
　
 

Rails チュートリアル　第6章　リスト6.5

```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 "should be valid" do
    assert @user.valid?
  end
end
```
<br>
assert メソッドは、第1引数がtrue である場合に、テストが成功したものとみなします。

setup メソッドで、テストが走る前に、インスタンス変数の @user を宣言し、valid?メソッドで有効性を確認しているわけですね。


assertメソッドにはそれ以外にも、
assert_not, assert_equal, assert_match などなど
数多くあるので、気になる方は、[こちら](http://ruby.studio-kingdom.com/rails/guides/testing#2)をご参照ください。


##機能テスト
`コントローラーの動作や、ビューの出力をチェックするためのテスト。`
HTTPリクエストを擬似的に作成することで、アクションメソッドを実行し、HTTPステータスやテンプレート変数、最終的な出力の構造までを確認する。また、ルーティングもチェックします。



 
 
コントローラって、アプリが受け付けたWebリクエストを処理して　
レンダリングされたビューを返しますよね。　
 　

機能テストでは、コントローラーのアクションが、リクエストや期待される結果（レスポンス、場合によってはHTMLビュー）をどう扱っているかをテストします。
つまり、以下のことを行うんです。



>
・Webリクエストが成功したか
・正しいページにリダイレクトされたか
・ユーザー認証が成功したか
・レスポンスのテンプレートに正しいオブジェクトが保存されたか
・ビューに表示されたメッセージは適切か


実際のコードを見てみましょう。

Rails チュートリアル第7章　リスト7.23 をご参照ください。

```app/controllers/users_controller.rb
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
```


```test/integration/users_signup_test.rb
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_</b>

`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でチェック|

<br>
Rails チュートリアルに、いっぱい出てきましたよね、これら・・・。
中でも、1つ個人的につまずいた、assert メソッドを抜粋します。
<br>

```
assert_select 'a[href=?]', about_path 
```
<br>
これは、about_path に合致するリンクが存在するかどうかを、確認しているものです。
この? が途中から、意味不明に見えてきたのですが、Railsチュートリアル  リスト5.32に
ちゃんと説明が書いてありました。
　
>
Railsは、自動的にはてなマーク "?" を about_pathに置換しています。
これにより、次のようなHTMLがあるかどうかをチェックすることができます。
\<a href="/about">...\</a>


なるほど納得ですね〜　
　
## 統合テスト
これは、`複数のコントローラーにまたがって、ユーザーの実際の操作を追跡する`用途で利用するテスト。

早速実際のコードを見てみましょう。


Rails チュートリアル　第5章　リスト5.32 
 
```test/integration/site_layout_test.rb
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
```

このコードは、今までの知識だけで理解できますね！　
私がつまずいたのは、 
 
<b>follow  redirect! </b>

そんなに、力を込めて、redirect！　するなよっていう気持ちでした.

Rails チュートリアル第8章　リスト8.23

```test/integration/users_login_test.rb
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
```


これ
この　<b>follow  redirect!</b>


なんで必要か？

よく探したら、Rails チュートリアル第7章に書いてありました。
>
このメソッドは、POSTリクエストを送信した結果を見て、指定されたリダイレクト先に移動するメソッドです。
　


あれ？これって、assert_redirected_to　メソッドと
どう違うんだろうと思いませんか？　
　

おそらくですが　
 
assert _redirected_to は、駅員が、「お客さんこの駅へ向かう切符でよろしいですか？」　
と確認すること　
　
　
follow_redirect!  は、 「その切符の行き先まで、実際に行くこと！」
の違いだと解釈しました。(違ってたら、コメントください。。)


*** 

なお、このテストの
<br>
`assert_redirected_to @user`
<br>
この書き方がよくわからない方。特に @user のとこ。
[こちら](https://qiita.com/Kawanji01/items/96fff507ed2f75403ecb)の記事が最高にわかりやすかったので、初心者の方は、ぜひ読んでみてくださいね！
 　　

簡単にまとめますと、
redirect_to のあとは絶対パスが来る。
→　user_url(@user.id) 
→　urlヘルパーと()は省略可能 →　@user.id
→　モデルオブジェクト@user って書けば、Railsが自動的にid 探す
→  @userになる。 
 
 
***
テストってかなり難しいと思います。
Railsチュートリアルを終わった今でも、かける自信はありません。
また、minitestの記事をググってもなかなか見つけることはできませんでした。　
　
この記事は、今後もバージョンアップして、少しでも皆様のお役に立てれればと思います。　
では、楽しいRails ライフを〜
<br>

参考文献：
Rails チュートリアル
Railsガイド
Ruby on Rails5  アプリケーションプログラミング