機能テスト冒頭部分の修正、等
2008/12/19
前回は、機能テストのうち main コントローラに関するテストが通るようにしました。
続いて、members コントローラをやっつけましょう。
> ruby test/functional/members_controller_test.rb (省略) 8 tests, 19 assertions, 1 failures, 2 errors
失敗が 1 個、エラーが 2 個。このくらいなら、すぐ終わりそうです。
エラーの原因は、前回同様ページネーション関係です。
# 会員一覧 def index (省略) if params[:group_id] @group = Group.find(params[:group_id]) @members = @group.members.find(:all, options) @member_pages = ActionController::Pagination::Paginator.new( self, @group.members.size, MEMBERS_PER_PAGE, page) else @members = Member.find(:all, options) @member_pages = ActionController::Pagination::Paginator.new( self, Member.count, MEMBERS_PER_PAGE, page) end end
を、次のように修正します。
# 会員一覧 def index (省略) if params[:group_id] @group = Group.find(params[:group_id]) @members = @group.members.all(options).paginate( :page => params[:page], :per_page => MEMBERS_PER_PAGE) else @members = Member.all(options).paginate( :page => params[:page], :per_page => MEMBERS_PER_PAGE) end end
そして、views/members/index.rhtml の次の部分
<% if @member_pages.page_count > 1 -%> <div class="pagination"> <%= my_pagination_links @member_pages %> </div> <% end -%>
を次のように修正します。
<%= will_paginate @members, :previous_label => '前へ', :next_label => '次へ', :inner_window => 2 %>
さて、失敗は test_routing で出ています。
3) Failure: test_routing(MembersControllerTest) [test/functional/members_controller_test.rb:26:in `test_routing' /usr/lib/ruby/gems/1.8/gems/activesupport-2.2.2/lib/active_support/testing/setup_and_teardown.rb:60:in `__send__' /usr/lib/ruby/gems/1.8/gems/activesupport-2.2.2/lib/active_support/testing/setup_and_teardown.rb:60:in `run']: The generated path <"/members/99/edit"> did not match <"/members/99;edit">
『基礎 Ruby on Rails』は Rails 1.2.3 準拠なのですが、Rails 1.2.4 で少し URL の形式が変わりました。
members というリソースを設定して、あるメンバーの情報を編集する入力フォームの URL が /members/99;edit
から /members/99/edit
に変更されたのです。
ということは、修正すべきはアプリケーション本体ではなくテストの方ということになります。
test/functional/members_controller_test.rb の 26-27 行目を次のように修正してください。
assert_generates 'members/99/edit', { :controller => 'members', :action => 'edit', :id => 99 }
さて、テストを実行すると一応すべて通りますが、警告が表示されます。
> ruby test/functional/members_controller_test.rb /home/kuroda/hgrepos/books/kiso_rails/cd-rom/chapter9/app/controllers/members_controller.rb:5: warning: already initialized constant MEMBERS_PER_PAGE Loaded suite test/functional/members_controller_test Started ........ Finished in 0.323797 seconds. 8 tests, 37 assertions, 0 failures, 0 errors
この警告は app/controllers/members_controller が二度 require されていることを示しています。
Rails 1.2 時代の機能テストの冒頭は次のように書かれていたのですが、
require File.dirname(__FILE__) + '/../test_helper' require 'members_controller' # Re-raise errors caught by the controller. class MembersController; def rescue_action(e) raise e end; end
Rails 2.2 になると次のようにシンプルになりました。
require 'test_helper'
つまり、コントローラのソースコードを明示的に require する必要はなくなり、コントローラがキャッチするエラーをレイズし直す必要もなくなったのです。
ただし、この Rails 2.2 方式にはちょっと問題があります。
test:functionals タスクを使って全ての機能テストを一括実行する場合はいいのですが、個々のテストスクリプトだけを単体で実行しようとすると
test/functional/members_controller_test.rb:1:in `require': no such file to load -- test_helper (LoadError) from test/functional/members_controller_test.rb:1
のように test_helper を require できず、止まってしまうのです。
昔風に次のように書けば大丈夫なのですが、
require File.dirname(__FILE__) + '/../test_helper'
Rails が生成する機能テストをいちいち修正するのは面倒です。
テストスクリプトの実行時に -Itest
オプションを付けるのが正しい方法です('-' の次の文字は、大文字の i です)。
> ruby -Itest test/functional/members_controller_test.rb
Ruby インタープリタの -I オプションは、ロードパス(require がファイルをロードする時に検索するディレクトリ)を指定するためのものです。
毎回 -Itest オプションを付けるのが面倒であれば、環境変数 RUBYOPT に '-Itest' をセットしてください。
bash なら
> export RUBYOPT=-Itest
Windows なら
> set RUBYOPT=-Itest
です。
なお、Rails 2.2 でこのような変更が行われた理由については、http://github.com/rails/rails/commit/e8170805 (英語)を参照してください。
これで、members コントローラは OK です。
test:functionals タスクを実行すると…
92 tests, 296 assertions, 3 failures, 6 errors
失敗の数が 4 から 3 に、エラーの数が 8 から 6 に減りました。
本日は、ここまで。