Help us understand the problem. What is going on with this article?

35歳だけどRailsチュートリアルやってみた。[第4版 7章 7.3.4 失敗時のテスト解答例]

More than 1 year has passed since last update.

はじめに

最近、プロジェクト管理業務が業務の大半を占めており、
プログラムを書く機会がなかなかありません。

このままだとプログラムがまったく書けない人になってしまう危機感(迫り来る35歳定年説)と、
新しいことに挑戦したいという思いから、
Ruby on Rails チュートリアル実例を使ってRailsを学ぼう 第4版を学習中です。
業務で使うのはもっぱらJavaなのですが、Rails楽しいですね。

これまでEvernoteに記録していましたが、ソースコードの貼付けに限界を感じたため、
Qiitaで自分が学習した結果をアウトプットしていきます。
(現時点で、7.3.4 失敗時のテストまで学習しているため、過去分も含めて今後はQiitaに以降予定です)

個人の解答例なので、誤りがあればご指摘ください。

7.3.4 失敗時のテスト

演習1

リスト 7.20で実装したエラーメッセージに対するテストを書いてみてください。どのくらい細かくテストするかはお任せします。リスト 7.25にテンプレートを用意しておいたので、参考にしてください。

エラー時のCSSクラスと、ID確認に加えて、
各エラーメッセージの有無を追加。

/sample_app/test/integration/users_signup_test.rb
  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'
    assert_select 'div#error_explanation'
    assert_select 'div.field_with_errors'
    assert_select 'ul' do
      assert_select 'li', 'Name can\'t be blank'
      assert_select 'li', 'Email is invalid'
      assert_select 'li', 'Password confirmation doesn\'t match Password'
      assert_select 'li', 'Password is too short (minimum is 6 characters)'
    end
  end

演習2

未送信のユーザー登録フォームと送信直後のURLは、それぞれ /signup と /users になり、URLが異なっています。これは、リスト 5.43で追加した名前付きルートと、デフォルトのRESTfulなルーティング (リスト 7.3) を設定したことによって生じた差異です。リスト 7.26とリスト 7.27の内容を追加し、この問題を解決してみてください。うまくいけば、いずれのURLも /signup となるはずです。あれ、でもテストは greenのままになっていますね...、なぜでしょうか? (考えてみてください)

以下の2ファイルを追加。

/sample_app/config/routes.rb
・・・略・・・
  post '/signup', to: 'users#create'
/sample_app/app/views/users/new.html.erb
・・・略・・・
    <%= form_for(@user, url: signup_path) do |f| %>

テスト実行。

yokoyan:~/workspace/sample_app (sign-up) $ rails test
Running via Spring preloader in process 6924
Started with run options --seed 57560

  19/19: [===================================================================================================================================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.32792s
19 tests, 47 assertions, 0 failures, 0 errors, 0 skips

テスト結果がgreenなのは、テストケースの中で
名前付きルートusers_pathにpostでリクエストを送信しているため。
結果、createアクション(ユーザを作成するアクション)が動いている。

HTTPリクエスト URL アクション   名前付きルート 用途
POST /users create users_path ユーザーを作成するアクション

現在のテストケース。

/sample_app/test/integration/users_signup_test.rb
・・・略・・・
    assert_no_difference 'User.count' do
      post users_path, params: { user: { name: "",
                                  email: "user@invalid",
                                  password: "foo",
                                  password_confirmation: "bar" } }
    end

演習3

リスト 7.25のpost部分を変更して、上の演習課題で作られた新しいURLに合わせてみましょう。また、テストが依然として greenのままになっている点も確認してください。

users_pathにpostしていた箇所を、signup_pathに修正。

/sample_app/test/integration/users_signup_test.rb
・・・略・・・
    assert_no_difference 'User.count' do
      post signup_path, params: { user: { name: "",
                                  email: "user@invalid",
                                  password: "foo",
                                  password_confirmation: "bar" } }
    end

テスト実行。
greenになることを確認。

yokoyan:~/workspace/sample_app (sign-up) $ rails test
Running via Spring preloader in process 7154
Started with run options --seed 3548

  19/19: [===================================================================================================================================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.25066s
19 tests, 47 assertions, 0 failures, 0 errors, 0 skips

演習4

リスト 7.27のフォームを以前の状態 (リスト 7.20) に戻してみて、テストがやはり greenになっていることを確認してください。これは問題です! なぜなら、現在postが送信されているURLは正しくないのですから。assert_selectを使ったテストをリスト 7.25に追加し、このバグを検知できるようにしてみましょう (テストを追加して redになれば成功です)。その後、変更後のフォーム (リスト 7.27) に戻してみて、テストが green になることを確認してみましょう。ヒント: フォームから送信してテストするのではなく、’form[action="/signup"]’という部分が存在するかどうかに着目してテストしてみましょう。

リスト7.20の状態に戻す。

/sample_app/app/views/users/new.html.erb
・・・略・・・
    <%= form_for(@user) do |f| %>

テスト実行。
greenになることを確認。

yokoyan:~/workspace/sample_app (sign-up) $ rails test
Running via Spring preloader in process 1732
Started with run options --seed 13591

  19/19: [===================================================================================================================================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.13653s
19 tests, 47 assertions, 0 failures, 0 errors, 0 skips

画面に表示されたフォーム部分のHTMLを確認。
action=/usersに対して、postしていることを確認。

・・・略・・・
<form class="new_user" id="new_user" action="/users" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="✓"><input type="hidden" name="authenticity_token" value="ef8dxHvKVDJUk1492ajabp7JpO3z5r3jPJokTlncPOhAps7rXszZ3Lipehod62SGD7k0i0aCw3V7578U4LEZ0w==">


      <label for="user_name">Name</label>
      <input class="form-control" type="text" name="user[name]" id="user_name">

      <label for="user_email">Email</label>
      <input class="form-control" type="email" name="user[email]" id="user_email">

      <label for="user_password">Password</label>
      <input class="form-control" type="password" name="user[password]" id="user_password">

      <label for="user_password_confirmation">Confirmation</label>
      <input class="form-control" type="password" name="user[password_confirmation]" id="user_password_confirmation">

      <input type="submit" name="commit" value="Create my account" class="btn btn-primary" data-disable-with="Create my account">
</form>

テストコードを追加。

/sample_app/test/integration/users_signup_test.rb
  test "invalid signup information" do
    get signup_path
    assert_no_difference 'User.count' do
      post signup_path, params: { user: { name: "",
                                  email: "user@invalid",
                                  password: "foo",
                                  password_confirmation: "bar" } }
    end
    assert_template 'users/new'
    assert_select 'div#error_explanation'
    assert_select 'div.field_with_errors'
    assert_select 'ul' do
      assert_select 'li', 'Name can\'t be blank'
      assert_select 'li', 'Email is invalid'
      assert_select 'li', 'Password confirmation doesn\'t match Password'
      assert_select 'li', 'Password is too short (minimum is 6 characters)'
    end
    assert_select 'form[action="/signup"]'
  end

再度テストを実行。
redになることを確認。

yokoyan:~/workspace/sample_app (sign-up) $ rails test
Running via Spring preloader in process 2967
Started with run options --seed 12420

 FAIL["test_invalid_signup_information", UsersSignupTest, 1.0442516568582505]
 test_invalid_signup_information#UsersSignupTest (1.04s)
        Expected at least 1 element matching "form[action="/signup"]", found 0..
        Expected 0 to be >= 1.
        test/integration/users_signup_test.rb:25:in `block in <class:UsersSignupTest>'

  19/19: [===================================================================================================================================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.41513s
19 tests, 48 assertions, 1 failures, 0 errors, 0 skips

フォームのアクションを修正。

/sample_app/app/views/users/new.html.erb
・・・略・・・
    <%= form_for(@user, url: signup_path) do |f| %>

画面に表示されたフォーム部のHTMLを確認。
action=/signupになっていることを確認。

<form class="new_user" id="new_user" action="/signup" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="✓"><input type="hidden" name="authenticity_token" value="SvCd4M/g92PHznf5vZouH+yAykUoH64pHgQdFvQWzp5zqU7P6uZ6jSv0U9552ZD3ffBaI5170L9ZeYZMTXvrpQ==">



      <label for="user_name">Name</label>
      <input class="form-control" type="text" name="user[name]" id="user_name">

      <label for="user_email">Email</label>
      <input class="form-control" type="email" name="user[email]" id="user_email">

      <label for="user_password">Password</label>
      <input class="form-control" type="password" name="user[password]" id="user_password">

      <label for="user_password_confirmation">Confirmation</label>
      <input class="form-control" type="password" name="user[password_confirmation]" id="user_password_confirmation">

      <input type="submit" name="commit" value="Create my account" class="btn btn-primary" data-disable-with="Create my account">
</form>

再度テストを実行。
greenになっていることを確認。

yokoyan:~/workspace/sample_app (sign-up) $ rails test
Running via Spring preloader in process 3051
Started with run options --seed 16395

  19/19: [===================================================================================================================================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.13927s
19 tests, 48 assertions, 0 failures, 0 errors, 0 skips

おわりに

はじめての投稿で緊張でした。
Markdownで書くのは敷居が高いと思っていましたが、
やってみたら楽しかったです。

これからどんどん情報発信するぞー。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away