テストの中で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にできるヘルパーを書きたくなります。

皆さんはこういうテストをどう書いてますか???