RailsのFunctionalテスト

Functionalテストの時に少しわかりにくかったところをメモするよ。

1.assert_response はHTTPステータスの確認を行うので、正常終了が基本。

最初はよくわからなかったのですが、assert_responseでチェックする対象というのはHTTPステータスなんですね。なので、基本的に正常に動作するということは 200:OK が取得できることになります。

Controllerのエラー処理を行った場合でも、HTTPステータスを変更したりしない限りは200:OK、つまりsuccessやRedirect時のコード(301や302)となります。ビジネスロジックの処理結果を判定するわけではないです。

[sourcecode language="ruby"] test "authentication fail" do

…

# 処理ステータスは200:OKが返ってくること
assert_response :success, 'HTTP status is not success.'

end [/sourcecode]

2.ビューで使用するテンプレート変数へはハッシュ値:assignsを使用してアクセスする。

ビューで使用するテンプレート変数は、ハッシュ値:assignsに保存されています。なので、たとえばエラーメッセージを取得したりする場合や表示するオブジェクトの確認を行う場合には、ハッシュ値:assigns から取得することができます。

なお、このハッシュ値:assigns は丸括弧'()'でキーを指定する方が便利だそうです。ブランケット'[]'の場合、シンボルを使用したハッシュ値へのアクセスができない(つまり、文字列でアクセスする)ためです。

[sourcecode language="ruby"] test "authentication fail" do

...

# 処理メッセージが正しいこと
assert_equal 'ユーザー名/パスワードが間違っています。', assigns(:error), '...'
...

end [/sourcecode]

3.request.headers["Accept-Language"]がnilだけどどのように設定していいかわからない

これは疑問点です。ロケールを設定するために、application_controller.rbに以下のような設定を行っていました。

[sourcecode language="ruby"]

coding:utf-8

class ApplicationController < ActionController::Base

# ロケールの設定用フィルタ before_filter :detect_local … private

def detect_local I18n.locale = request.headers["Accept-Language"].scan(/^[a-z]{2}/).first end

… end [/sourcecode]

この状態でFunctionalテストを実行すると、scanメソッドが存在しないエラーが出力されます。Rubyのエラーで「…メソッドが存在しない」というのは、経験上対象となるオブジェクトがnilや型違いの場合が多かったのですが、調べてみるとrequest.headers["Accept-Language"]がnilになっていました。

request.headers["Accept-Language"]がnilと言うことであれば、話は簡単で設定してあげればいいかと思ったのですが、値を設定するタイミングがいまいちわからない…。FunctionalテストでControllerオブジェクトを生成する際には特にそのようなパラメータは存在しないし、生成する際にエラーになるから…。

[sourcecode language="ruby"] test "authentication fail" do

# ここでControllerの初期化と生成が行われるがエラーとなる
get:auth, {:userid =&gt; nil, :password =&gt; nil}

...

end [/sourcecode]

ということで、国際化対応については一時ペンディングしています。そのうち、時間を見つけて調べてみようと思います。

なお、Functionalテストについては、やはりこの書籍に説明があります。