内容
Railsチュートリアル第13章の本文中において、テストが書かれることなしに実装されていた以下2つの要素を、テスト駆動で実装してみようというものです。
- ユーザー情報のパーシャル
- マイクロポスト投稿フォーム
Railsチュートリアル本文においては、「マイクロポスト作成フォームのあるホーム画面のモックアップ」として、図 13.10が挙げられています。
ユーザー情報のパーシャルの実装
ユーザー情報のパーシャルに含まれているべき要素に対するテスト
Railsチュートリアル本文によれば、サイドバーで表示されるべきユーザー情報のパーシャルには、以下の要素が含まれている必要があります。
-
gravatar_for
クラスを持つimg
要素 - ユーザー名を内容とする
h1
要素 - マイクロポスト数を含む
span
要素
テストを追加するのはtest/integration/microposts_interface_test.rb
です。追加するテストの内容は以下となります。
require 'test_helper'
class MicropostsInterfaceTest < ActionDispatch::IntegrationTest
def setup
@user = users(:rhakurei)
end
test "micropost interface" do
log_in_as(@user)
get root_path
+ assert_select 'img.gravatar'
+ assert_select 'h1', @user.name
+ assert_select 'span', /#{@user.microposts.count}/
assert_select 'div.pagination'
...略
end
end
「指定の文字列が含まれる指定の要素が存在するか」というテスト
例えば「@user.microposts.count
変数の内容が記述されているspan
要素が存在するか」というテストであれば、以下のように記載します。
assert_select 'span', /#{@user.microposts.count}/
正規表現オブジェクトを意味する//
で、変数の内容を展開する#{}
を囲っているのがポイントですね。
サイドバーで表示されるべきユーザー情報のパーシャルに対しての、現時点のテスト結果
現時点でのtest/integration/microposts_interface_test.rb
に対するテストの結果は、以下のようになります。
# rails test test/integration/microposts_interface_test.rb
Running via Spring preloader in process 120
Started with run options --seed 17602
FAIL["test_micropost_interface", MicropostsInterfaceTest, 3.629997299999559]
test_micropost_interface#MicropostsInterfaceTest (3.63s)
Expected at least 1 element matching "h1", found 0..
Expected 0 to be >= 1.
test/integration/microposts_interface_test.rb:12:in `block in <class:MicropostsInterfaceTest>'
1/1: [===================================] 100% Time: 00:00:03, Time: 00:00:03
Finished in 3.63972s
1 tests, 2 assertions, 1 failures, 0 errors, 0 skips
「h1
要素が見当たらない」というメッセージを出してテストが失敗しています。
サイドバーで表示するユーザー情報のパーシャルを実装する
まず、サイドバーで表示するユーザー情報のパーシャルの実体を実装していきます。ファイル名はapp/views/shared/_user_info.html.erb
とします。
<%= link_to gravatar_for(current_user, size: 50), current_user %>
<h1><%= current_user %></h1>
<span><%= link_to "view my profile", current_user %><span>
<span><%= pluralize(current_user.microposts.count, "micropost") %></span>
続いて、Homeページのビューでも当該パーシャルを使用するようにします。変更するファイルはapp/views/static_pages/home.html.erb
ですね。
<% provide(:title, "Home") %>
<% if logged_in? %>
<div class="row">
<aside class="col-md-4">
- <%#TODO: ユーザー情報表示部の実装 %>
+ <section class="user_info">
+ <%= render 'shared/user_info' %>
+ </section>
<section class="micropost_form">
<%= render 'shared/micropost_form' %>
</section>
</aside>
<div class="col-md-8">
<h3>Micropost Feed</h3>
<%= render 'shared/feed' %>
</div>
</div>
<% else %>
...略
<% end %>
サイドバーで表示するユーザー情報のパーシャルを実装した時点でのテストの結果
ここまでの実装が完了した時点で、test/integration/microposts_interface_test.rb
を対象としてテストを実行すると、結果は以下のようになります。
# rails test test/integration/microposts_interface_test.rb
Running via Spring preloader in process 224
Started with run options --seed 14923
1/1: [===================================] 100% Time: 00:00:03, Time: 00:00:03
Finished in 3.96801s
1 tests, 13 assertions, 0 failures, 0 errors, 0 skips
テストが成功していますね。ひとまず、サイドバーで表示するユーザー情報のパーシャルは正しく追加できたようです。
マイクロポスト投稿フォームの完全な実装
完全なマイクロポストの投稿フォームに含まれているべき要素に対するテスト
Railsチュートリアル本文によれば、サイドバーで表示されるべきマイクロポスト投稿フォームのパーシャルには、以下の要素が含まれている必要があります。
- /microposts に対して
POST
アクションを行うフォーム - マイクロポスト本文を入力するためのテキストフィールド
require 'test_helper'
class MicropostsInterfaceTest < ActionDispatch::IntegrationTest
def setup
@user = users(:rhakurei)
end
test "micropost interface" do
log_in_as(@user)
get root_path
assert_select 'img.gravatar'
assert_select 'h1', @user.name
assert_select 'span', /#{@user.microposts.count}/
+ assert_select 'form[action="/microposts"]'
+ assert_select 'textarea'
assert_select 'div.pagination'
...略
end
end
マイクロポスト投稿フォームに対するテストを実装した時点でのテストの結果
上記マイクロポスト投稿フォームに対するテストを実装した時点で、microposts_interface_test.rb
に対してテストを実行してみましょう。
# rails test test/integration/microposts_interface_test.rb
Running via Spring preloader in process 276
Started with run options --seed 9808
FAIL["test_micropost_interface", MicropostsInterfaceTest, 3.1817765000014333]
test_micropost_interface#MicropostsInterfaceTest (3.18s)
Expected at least 1 element matching "textarea", found 0..
Expected 0 to be >= 1.
test/integration/microposts_interface_test.rb:15:in `block in <class:MicropostsInterfaceTest>'
1/1: [===================================] 100% Time: 00:00:03, Time: 00:00:03
Finished in 3.19284s
1 tests, 5 assertions, 1 failures, 0 errors, 0 skips
「textarea
要素が存在しない」というメッセージを出力してテストが失敗しています。
マイクロポスト投稿フォームの完全な実装
Railsチュートリアル本文によれば、マイクロポスト投稿フォームの完全な実装は以下の通りになります。
<%= form_for(@micropost) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :content, placeholder: "Compose new micropost..." %>
</div>
<%= f.submit "Post", class: "btn btn-primary" %>
<% end %>
対応するソースファイルはtest/integration/microposts_interface_test.rb
です。
ここまでの実装で、エラーメッセージのパーシャルが出力できるようにするための実装は完了しています。新たに追加する必要があるのは以下の2つですね。
- マイクロポスト本文を入力するためのテキストフィールド
- 送信ボタン
早速実装を追加していきましょう。
<%= form_for(@micropost) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
+ <div class="field">
+ <%= f.text_area :content, placeholder: "Compose new micropost..." %>
+ </div>
+ <%= f.submit "Post", class: "btn btn-primary" %>
<% end %>
マイクロポスト投稿フォームの完全な実装を終えた時点でのテストの結果
test/integration/microposts_interface_test.rb
に対し、改めてテストを実行してみましょう。
# rails test test/integration/microposts_interface_test.rb
Running via Spring preloader in process 341
Started with run options --seed 28502
1/1: [===================================] 100% Time: 00:00:04, Time: 00:00:04
Finished in 4.07368s
1 tests, 15 assertions, 0 failures, 0 errors, 0 skips
今度こそテストが成功しました。
テストスイート全体に対するテストの結果はどうでしょうか。
# rails test
Running via Spring preloader in process 354
Started with run options --seed 14679
59/59: [=================================] 100% Time: 00:00:11, Time: 00:00:11
Finished in 11.81368s
59 tests, 321 assertions, 0 failures, 0 errors, 0 skips
テストスイート全体に対しても、無事テストが成功しましたね。