投稿の目的
- Railsが、4.2.6から5になることで変わるポイントを記録すること
動機
- 以前にもRails Tutorialで勉強していました
- が、テストはそれ以降敬遠していた
- やはり自動でできるテストはせっかくある機能に任せるべきだと思うに至った
ということで、テストに関する知識を復習をして、"テストを書く→コードを書く"を習慣づけたいと思い改めてチュートリアルをやろうと思いました。それであれば、せっかくRails5がリリースされているので、Rails5で変わったことを忘れないように記録したいと思います。
チュートリアルをやりながら、気づいたら追記をしていきます。
環境
- ubuntu 16.04
- Rails 5.0.0.1
- Ruby 2.3.1
3.3.1 最初のテスト
rails generate
で作られたstatic_pages_controller_test.rb
のコントローラーのテストファイルにおいて、ページを呼び出すget
で設定する値がシンボルではなく、URLやPATHでないとURI::InvalidURIError: URI::InvalidURIError: bad URI(is not URI?)
というエラーが出てテストがfailする。
# Rails 4.2.6
require 'test_helper'
class StaticPagesControllerTest < ActionController::TestCase
test "should get home" do
get :home # <- ここ
assert_response :success
end
test "should get help" do
get :help # <- ここ
assert_response :success
end
end
# Rails 5.0.0.1
require 'test_helper'
class StaticPagesControllerTest < ActionDispatch::IntegrationTest
test "should get home" do
get static_pages_home_url # <- ここ
assert_response :success
end
test "should get help" do
get static_pages_help_url # <- ここ
assert_response :success
end
end
継承されているclassが5で変わったことが影響しているのかな。あとで調べる。
<2016/9/8 追記>
5.3.4. リンクのテスト
統合テスト(integration test)を実行すると、次のエラーが出る。
ERROR["test_layout_links", SiteLayoutTest, 0.7033021890001692]
test_layout_links#SiteLayoutTest (0.70s)
NoMethodError: NoMethodError: assert_template has been extracted to a gem. To continue using it,
add `gem 'rails-controller-testing'` to your Gemfile.
test/integration/site_layout_test.rb:6:in `block in <class:SiteLayoutTest>'
ここやこちらにあるように、testについて、assigns
やassert_template
がrails5では非推奨になったためのようです。
エラーに書かれている通りにgem 'rails-controller-testing'
をgemfileに追加してget xxxを修正して実行すると問題なくテストできました。
require 'test_helper'
class StaticPagesControllerTest < ActionDispatch::IntegrationTest
def setup
@base_title = 'Ruby on Rails Tutorial Neo Sample App'
end
test "should get home" do
get root_url
assert_response :success
assert_select "title", "#{@base_title}"
end
test "should get help" do
get help_url
assert_response :success
assert_select "title", "Help | #{@base_title}"
end
test "should get about" do
get about_url
assert_response :success
assert_select "title", "About | #{@base_title}"
end
test 'should get contact' do
get contact_url
assert_response :success
assert_select 'title', "Contact | #{@base_title}"
end
end
7.4.4. 成功時のテスト
以下のテストを実行すると、成功するものの要約すると3つのdeprecation warningが表示される。
1. httpリクエストのパラメータの設定方法が変更になり、パラメータをparams
に入れる。
2. post_via_redirect
の代わりにfollow_redirect!
を利用する。
DEPRECATION WARNING: ActionDispatch::IntegrationTest HTTP request methods will accept only ] 19% Time: 00:00:08, ETA: 00:00:36
the following keyword arguments in future Rails versions:
params, headers, env, xhr, as
Examples:
get '/profile',
params: { id: 1 },
headers: { 'X-Extra-Header' => '123' },
env: { 'action_dispatch.custom' => 'custom' },
xhr: true,
as: :json
(called from block (2 levels) in <class:UsersSignupTest> at /home/ebill/work/neo_sample_app/test/integration/users_signup_test.rb:8)
DEPRECATION WARNING: `post_via_redirect` is deprecated and will be removed in Rails 5.1. Please use `follow_redirect!` manually after the request call for the same behavior. (called from block (2 levels) in <class:UsersSignupTest> at /home/ebill/work/neo_sample_app/test/integration/users_signup_test.rb:19)
DEPRECATION WARNING: `request_via_redirect` is deprecated and will be removed in Rails 5.1. Please use `follow_redirect!` manually after the request call for the same behavior. (called from block (2 levels) in <class:UsersSignupTest> at /home/ebill/work/neo_sample_app/test/integration/users_signup_test.rb:19)
DEPRECATION WARNING: ActionDispatch::IntegrationTest HTTP request methods will accept only
the following keyword arguments in future Rails versions:
params, headers, env, xhr, as
Examples:
get '/profile',
params: { id: 1 },
headers: { 'X-Extra-Header' => '123' },
env: { 'action_dispatch.custom' => 'custom' },
xhr: true,
as: :json
(called from block (2 levels) in <class:UsersSignupTest> at /home/ebill/work/neo_sample_app/test/integration/users_signup_test.rb:19)
21/21: [===============================================================================================] 100% Time: 00:00:09, Time: 00:00:09
Finished in 9.07180s
21 tests, 41 assertions, 0 failures, 0 errors, 0 skips
require 'test_helper'
class UsersSignupTest < ActionDispatch::IntegrationTest
test 'invalid signup information' do
get signup_path
assert_no_difference 'User.count' do
post users_path, user: { name: '',
email: 'invalid@email.com',
password: 'foo',
password_confirmation: 'bar'}
end
assert_template 'users/new'
end
test 'valid signup information' do
get signup_path
assert_difference 'User.count', 1 do
post_via_redirect users_path, user: { name: 'Example User',
email: 'valid@email.com',
password: 'password',
password_confirmation: 'password'}
end
assert_template 'users/show'
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: 'invalid@email.com',
password: 'foo',
password_confirmation: 'bar'}}
end
assert_template 'users/new'
end
test 'valid signup information' do
get signup_path
assert_difference 'User.count', 1 do
post users_path, params: { user: { name: 'Example User',
email: 'valid@email.com',
password: 'password',
password_confirmation: 'password'}}
follow_redirect!
end
assert_template 'users/show'
end
end
<2016/9/13追記>
9.2.1 ユーザーにログインを要求する
上述の7.4.4.で記載されているとおり、テストにおいて、httpリクエストのパラメータの渡し方が変更になっている。
require 'test_helper'
class UsersControllerTest < ActionController::TestCase
def setup
@user = users(:michael)
end
test "should get new" do
get :new
assert_response :success
end
test "should redirect edit when not logged in" do
get :edit, id: @user
assert_not flash.empty?
assert_redirected_to login_url
end
test "should redirect update when not logged in" do
patch :update, id: @user, user: { name: @user.name, email: @user.email }
assert_not flash.empty?
assert_redirected_to login_url
end
end
require 'test_helper'
class UsersControllerTest < ActionDispatch::IntegrationTest
def setup
@user = users(:michael)
end
test "should get new" do
get signup_path
assert_response :success
end
test "should redirect edit when not logged in" do
get edit_user_path(@user)
assert_not flash.empty?
assert_redirected_to login_url
end
test "should redirect update when not logged in" do
patch user_path(@user), params: { user: { name: @user.name, email: @user.email } }
assert_not flash.empty?
assert_redirected_to login_url
end
end
9.4.3. ユーザー削除のテスト
上述の7.4.4.で記載されているとおり、テストにおいて、httpリクエストのパラメータの渡し方が変更になっている。
require 'test_helper'
class UsersControllerTest < ActionController::TestCase
def setup
@user = users(:michael)
@other_user = users(:archer)
end
.
.
.
test "should redirect destroy when not logged in" do
assert_no_difference 'User.count' do
delete :destroy, id: @user
end
assert_redirected_to login_url
end
test "should redirect destroy when logged in as a non-admin" do
log_in_as(@other_user)
assert_no_difference 'User.count' do
delete :destroy, id: @user
end
assert_redirected_to root_url
end
end
require 'test_helper'
class UsersControllerTest < ActionDispatch::IntegrationTest
def setup
@user = users(:michael)
@other_user = users(:archer)
end
.
.
.
test "should redirect destroy when not logged in" do
assert_no_difference("User.count") do
delete user_path(@user)
end
assert_redirected_to login_url
end
test "should redirect destroy when logged in as a non-admin" do
log_in_as(@other_user)
assert_no_difference("User.count") do
delete user_path(@user)
end
assert_redirected_to root_url
end
end