テストの中でnamed routesを使う
テストコードにおいて、RESTfulなURLへのリンクやformのactionがあることをassertする場合、どう書きますか?例えば下のようなリンクが表示されることを確認したい場合です。
<a href="/products/1;edit">
下のようにパスをハードコードしてしまったら、
assert_select "a[href = /products/1;edit]"
Rails 2.0でパスのスキーマが変わった時(/products/1;edit
が/products/1/edit
になった時)テストコードを書き直さなければなりません。
コントローラで使える名前付きルート(named routes, resource routes)はprotectedなので、次のように書くと
assert_select "a[href = #{@controller.edit_product_path(1)}]"
エラーになります。
url_for
はpublicメソッドなので下のように書くことができますが((link_to
で生成されるのはパスのみなので、url_for
で同じパスを作るには:only_path
オプションが必要です。))
assert_select "a[href = #{@controller.url_for(:action => 'edit', :id => 1, :only_path => true)}]"
resource routeがあるものをurl_for
で書くのは何だかカッコ悪いです。
テストの間だけnamed routesをpublicに
テストコードの中で次のように書いてやると、上に出てきたedit_product_path
を使えるようになります。
class ProductsController public :edit_product_path end
例えばこの例だと、products_controller_test.rbのclass ProductsControllerTest < Test::Unit::TestCase
などと書いてある行の上にでも書けば十分でしょう。
protectedのようなアクセス制限は、本来プログラマーにオブジェクト指向に従ったコーディングを促し、ソフトウェアの品質を高めるために存在するので、むやみに解除すべきではありませんが、テストコードの中でのみ使う限り問題ないと思われます。
この方法の問題点は、数あるnamed routesを使う分だけ列挙する必要があることです。個人的な感覚では5,6個までなら我慢できますが、それ以上になったらまとめてpublicにできるヘルパーを書きたくなります。
皆さんはこういうテストをどう書いてますか???