LoginSignup
13
11

More than 5 years have passed since last update.

Rails5でRails Tutorial(Rails4.2.6)をやってみた

Last updated at Posted at 2016-09-02

投稿の目的

  • 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する。

test/controllers/static_pages_controller_test.rb
# 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について、assignsassert_templateがrails5では非推奨になったためのようです。

エラーに書かれている通りにgem 'rails-controller-testing'をgemfileに追加してget xxxを修正して実行すると問題なくテストできました。

static_pages_controller_test.rb
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

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, 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

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: '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リクエストのパラメータの渡し方が変更になっている。

修正前users_controller_test.rb
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
修正後users_controller_test.rb
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リクエストのパラメータの渡し方が変更になっている。

修正前users_controller_test.rb
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
修正後users_controller_test.rb
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
13
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
11