まさ@ブログ書き込み中

まさ@ブログ書き込み中

まさの旅、英語、プログラミング、プライベートについて、色々記録しています。

Railsチュートリアルの7章の内容が思ってたより深い【テスト編】

 

おはようございます、まさです。

 

昨日僕はRailsチュートリアルの7章の内容について書きました。

masa-world.hateblo.jp

 

しかし本当のRailsチュートリアルの醍醐味は、テストコードと言っても過言ではありません(思いっきり過言)。

 

というわけで、今まで取り上げてこなかったテストコードについてまとめていきたいと思います。

 

 

失敗時のテスト

昨日の記事でも書いたように、第7章はユーザー登録のための実装を行いました。

 

次はそれがうまく動くかどうかテストしなければなりません。その際に一々有効なデータと無効なデータを交互に流し込みチェックすることもできますが、Railsではフォーム用のテストを書くことができます。

 

統合テストの生成

まずは新規ユーザー登録用の統合テストを生成します。コントローラーの慣習「リソース名は複数形」(users_controller.rbなど)に従って統合テストのファイル名はusers_signupとします。

rails generate integration_test users_signup

 

リソースについて

ここまで書いて、僕は皆さんに補足しなければならないことがあることに気づきました。

Railsチュートリアルの7章の内容が思ってたより深い【要約編】 - まさ@ブログ書き込み中

で書いていた内容では、リソースとは

HTTPプロトコル経由で自由にCURD(作成/読み出し/更新/削除)できる(分類された)データ群

と紹介しましたが、これはリソースの中の「モデル」にのみ焦点をあてた説明となっていました。

 

このサイトがわかりやすく、より詳しく説明してくれています。

stonebeach-dakar.hatenablog.com

 

このサイトによると、リソースとは「コントローラが扱う対象に名前をつけたもの」であり、モデルのみならず、セッション、画像、ファイル等もリソースと言えるらしいです。

 

テストコードの組み立て方

ここでは失敗すべきユーザー登録を行わせ、その前後でUserモデルのインスタンスの数(ユーザー数)が変わっていないかどうかを調べます。

 

その際に役に立つのがcountメソッド。

$ rails console
>> User.count
=> 1

このようにUser.countとするとそのUserモデルのインスタンスの数を把握できます。

 

テストする際によく出てくるのがassert_<hoge>というメソッドです。英語でassertは「断言する」とあるようにテストの際に予想する反応を「こうなるよ」と宣言しておくようなものです。この宣言通りになればテストは通ります(パス)し、ならなければエラーが出ちゃいます。

 

また、テスト内でユーザー登録ページにアクセスするために名前付きルートのsignup_pathを使い

get signup_path

と書きます。

 

ちなみに、名前付きルートの復習になりますが、signup_pathが使えるのはルーティングを

get '/signup', to: 'users#new

としているからです。

 

最終的に、テストコードは以下のようになります。

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

 

順を追って説明すると、

  1. まずはテストが始まると、getメソッドでユーザー登録ページにアクセス。
  2. assert_no_diffrenceは文字通りUser.countに変化が起こらないと宣言しています。
  3. その中でpostメソッドで登録が失敗すべき様々なデータ(params)を送信します。
  4. 最後のassert_template 'users/new'は、users/new.html.erbが最後にビューとして描画されているかどうかをチェックするメソッドです。今回はユーザー登録が失敗した場合、new.html.erbページを表示するようにしているため、このテストを書きました。

f:id:masaincebu:20170828102026p:plain

createメソッドが失敗したらrender 'new'(new.html.erbを描画)するようになっています。

 

postはともかく、users_pathに関して僕は「ん?なにこれ」と思ったんですが、昨日の記事で書いたようにresources :usersとしたことで以下のようなルートが使えるようになるんでしたね。

f:id:masaincebu:20170828100645p:plain

 

Usersリソース(ここではUserモデル)がRESTfulであるということは、HTTPリクエストと連動するということですから、HTTPリクエストがPOSTメソッドで、URIが/users(users_path)であれば、createアクションに紐づけられるわけですな。

 

よって、

$ rails test

でテストは成功するはずです。

 

 

成功時のテスト

同じように、成功時のテストをする場合には

  test "valid signup information" do
    get signup_path
    assert_difference 'User.count', 1 do
      post users_path, params: { user: { name:  "Example User",
                                         email: "user@example.com",
                                         password:              "password",
                                         password_confirmation: "password" } }
    end
    follow_redirect!
    assert_template 'users/show'
  end

と書きます。

assert_no_differenceがassert_differenceになっていることに注意してください。

 

また、follow_redirect!は「POSTリクエストを送信した結果を見て、指定されたリダイレクト先に移動するメソッド」だそうです。ちなみに、このアプリケーションではユーザー登録がうまくいった場合そのユーザーのページ(users/show.html.erb)にリダイレクトするようにしています。assert_template 'users/show'はそれをチェックしているわけですね。

 

 

感想

いやあ、本当になめてた。

7章のテストについて書くだけでこんなに時間がかかるとは・・・。

 

でも何事もしっかり人に説明できるくらい理解することが大切だと考えているため、別に問題はないかなと思っています。

 

ではいち早く8章・9章のまとめをかけるように頑張りますー。