Rails tutorialの第3章を終えました。
その時の気づいたこととか備忘録です。
今回はユニットテストについて
テスト対象コード
Railsでユニットテストを行う際は
テストコードを書いたあと
$ rails test
もしくは
$ rails t
で行えます。
静的ページのテスト
ここでは静的なページについてテストすることを見ます。
例: /app/view/hoge
に静的なページ(home.html.erb)を作成し
そのページにTitle(Home | SampleApp)をつけるとします。
ユニットテスト
ここではテスト項目として
- アクセスできるか
- Titleがあっているか
をあげます。
上記を元にテストコードとしては下記が一つあげれます。
/test/controllers/Hoge_controller_test.rb
require 'test_helper' class HogeControllerTest < ActionDispatch::IntegrationTest test "should get home" do get hoge_home_url assert_response :success assert_select "title", "Home | SampleApp" end end
get hoge_home_url
:GETリクエストをhomeアクションに発行。
assert_response :success
はHTTP レスポンスは成功(200)が帰ってくればOK
assert_select "title", "Home | SampleApp"
はここではtitleタグは"Home | SampleApp"
となります。
viewやコントローラの設定を行っていない場合やルーティングを行っていない場合
$ rails t
を行っても当然ユニットテストは失敗します。
$ rails test NameError: undefined local variable or method `hoge_home_url' 1 tests, 2 assertions, 2 failures, 0 errors, 0 skips
実装
次に、テストが通るように諸々設定してみます。
/app/views/hoge/home.html.erb
<!DOCTYPE html> <html> <head> <title>Home | SampleApp</title> </head> <body> <h1>Sample App</h1> <p> This is the home page </p> </body> </html>
/config/route.rb
Rails.application.routes.draw do get 'static_pages/home' end
/app/controllers/hoge_controller.rb
class HogeController < ApplicationController def home end end
こんな感じで書いてあげて、再び$rails t
を行うと、
テストが通ってくれます。
$ rails test 1 tests, 2 assertions, 0 failures, 0 errors, 0 skips
複数ページのテスト
最後に同様の静的ページを複数作成し、
ついでにrootをルーティングした想定でテストを書きます。
/test/controllers/Hoge_controller_test.rb
def setup @base_title = "SampleApp" end test "should get root" do get root_url assert_response :success end test "should get home" do get static_pages_home_url assert_response :success assert_select "title", "Home | #{@base_title}" end test "should get help" do get static_pages_help_url assert_response :success assert_select "title", "Help | #{@base_title}" end
ここでsetup
メソッドは、各テスト実施前に実行を行うメソッドです。
Railsでは各テストの準備のためのメソッドとしてsetup
メソッドを定義することで
他に何も設定しなくても勝手に実行できます。
また、root_url
でGETリクエストをroute.rb内のrootに定義したアクションに発行しにいきます
実装
このテストを通します。
新規作成:/app/views/hoge/help.html.erb
<!DOCTYPE html> <html> <head> <title>Help | SampleApp</title> </head> <body> <h1>Sample App</h1> <p> This is the home page </p> </body> </html>
/config/route.rb
Rails.application.routes.draw do get 'static_pages/home' #下記追加 get 'static_pages/help' root 'static_pages#hello' end
/app/controllers/hoge_controller.rb
class HogeController < ApplicationController def home end #下記追加 def help end end
こんな感じにすれば通るかと思います。
$ rails test 3 tests, 5 assertions, 0 failures, 0 errors, 0 skips
リファクタリング
最後に、erbの重複している部分をlayouts/application_hepler.erb
に逃がしてあげたら
いい感じになると思います。
layouts/application_hepler.erb
<!DOCTYPE html> <html> <head> <title> <%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title> <%= csrf_meta_tags %> <%= csp_meta_tag %> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> </head> <body> <%= yield %> </body> </html>
この際、viewに<% provide(:title, "Hoge") %>
のように記述すると
application_hepler.erb
で<%= yield(:title) %> | "Hoge"
のように使用することができます。
(余談)
application.html.erbはアプリケーションを新規作成した際に自動で作成されます
その際にCSSやJSについても自動で作成されます
またCSRFについては別記事にあります
onthebacksoftheflyer.hatenadiary.jp
CSPについては下記に詳しいです
qiita.com
あとはそれぞれのviewをいじってあげて、もう一度テストするといい感じかと思います
/app/views/hoge/help.html.erb
<% provide(:title, "Help") %> <h1>Help</h1> <p> This is the home page </p>
/app/views/hoge/home.html.erb
<% provide(:title, "Home") %> <h1>Help</h1> <p> This is the home page </p>
あとはテストを通したらいい感じです。
$ rails test 3 tests, 5 assertions, 0 failures, 0 errors, 0 skips
これを書いている人
業務でもユニットテストやったことない。
単体テストと言われたら、結果の画面キャプチャをエクセルで貼り付けてた人
このRailsチュートリアルが初めて、まともにテストコード書いて結果をコンソールで確認する人