機能テストコードの実装
機能テストでは、Controllerのアクションメソッドごとに、メソッド処理の確認コードを実装していきます。
都合の良いことに、スカフォルド機能でControllerを作成したことで、機能テストコードについてもベース部分が作成されています。
そこで、まずはスカフォルド機能により作成された機能テストコードを確認していきます。
[Railsエクスプローラー]からtsubuyakiプロジェクト−[テスト]−[機能テスト]の順にツリーを展開し、HitokotosControllerをダブルクリックすると、編集エリアに以下のとおりHitokotosControllerの機能テストコード(hitokotos_controller_test.rb)が表示されます。
require 'test_helper' class HitokotosControllerTest < ActionController::TestCase test "should get index" do get :index assert_response :success assert_not_nil assigns(:hitokotos) end test "should get new" do get :new assert_response :success end test "should create hitokoto" do assert_difference('Hitokoto.count') do post :create, :hitokoto => { } end assert_redirected_to hitokoto_path(assigns(:hitokoto)) end test "should show hitokoto" do get :show, :id => hitokotos(:one).id assert_response :success end test "should get edit" do get :edit, :id => hitokotos(:one).id assert_response :success end test "should update hitokoto" do put :update, :id => hitokotos(:one).id, :hitokoto => { } assert_redirected_to hitokoto_path(assigns(:hitokoto)) end test "should destroy hitokoto" do assert_difference('Hitokoto.count', -1) do delete :destroy, :id => hitokotos(:one).id end assert_redirected_to hitokotos_path end end
では、機能テストコードの書き方を含め、作成されたコードを確認していきましょう。
上記のとおり、機能テストコードはActionController::TestCaseを継承したクラスへ記述します(ちなみに、Modelクラスのユニットテストコードは、ActiveSupport::TestCaseを継承したクラスに記述してきました)。このクラスを継承しておくことで、機能テストコード内において、Controllerへの各種HTTPリクエスト発行やレスポンス確認を行うための処理を簡単に記述できます。
サンプルとして、上記のコードの最初のテストケースを見ていきましょう。
test "should get index" do get :index assert_response :success assert_not_nil assigns(:hitokotos) end
テストケースは、ユニットテストコードを記述したときと同様、testメソッドのブロック内に記述していきます。testメソッドへの引数も同様に、任意の文字列が指定できますので、テスト内容を表現した文字列を書いていくと良いでしょう。
このテストケースでは、should get indexとなっていますので、このブロックでは「HitokotosControllerからindex(一覧)を取得できるべき」というテストを記述していることが分かります。
続いて、ブロック内の処理も確認してみましょう。
最初のget :indexという行を見てください。getはアクションメソッド名シンボルを引数にとるメソッドです。つまり、HitokotosControllerのindexアクションを呼び出すためのHTTP GETリクエストを発行することを示しています。
同様にPOST、PUT、DELETEなどのHTTPリクエストに対応したメソッドも用意されています。後ほど出てきますので、確認しておきましょう。
次に、assert_response :successという行ですが、ここではassert_responseというメソッドで、ControllerからのHTTPレスポンスを検証しています。引数として:successシンボルを指定することで、HTTPレスポンスのステータスコードが正常(200)であることが検証できます。
ほかのステータスを検証するためのシンボルとして、:redirect(リダイレクト/ステータスコード3xx)、:missing(発見できず/ステータスコード404)、:error(エラー/ステータスコード5xx)なども指定できます。
最後に、assert_not_nil assigns(:hitokotos)の行ですが、この行では、assigns(:hitokotos)の評価結果がnilでないことを検証しています。assignsというのは、引数としてControllerのインスタンス変数名をシンボル指定することで、そのインスタンス変数の持つ値を返すメソッドです。
従って、この行では、HitokotosController#indexが実行されたとき、インスタンス変数@hitokotosがnilでないことを検証しています。
つまり、このテストケースをまとめると「HitokotosControllerからindex(一覧)を取得できるべき」という検証ステップとして、
- HitokotosController#indexアクションを呼び出すHTTP GETリクエストを発行し、
- HTTPレスポンスのステータスコードが200であることを検証し、
- アクション実行後にインスタンス変数@hitokotosがnilでないことを検証する
という処理が書かれていることが分かります。
続くnewアクションのテストケースは、indexと同様なので説明を飛ばします。続いて、createアクションのテストケースは、以下のようになっています。
test "should create hitokoto" do assert_difference('Hitokoto.count') do post :create, :hitokoto => { } end assert_redirected_to hitokoto_path(assigns(:hitokoto)) end
ここでは、「HitokotosControllerがHitokotoモデルを作成できるべき」というテストが記述されています。
assert_differenceという行ですが、これは、ある特定の処理の前後で、引数の値(評価結果)が変動することを検証するための行となっています。ある特定の処理は、assert_diferrenceのブロック内に記述します。
ここでは、引数として'Hitokoto.count'を指定していますので、ModelクラスHitokotoのレコード数が、ブロック内の処理post :create, :hitokoto => { }の実行前後で変更されることを検証しています。
このテストケースが実行される際の流れは以下のようになっていることになります。
- まず引数の評価を行い、その値を記録する
- ブロック内処理を実行する
- 再度、引数の評価を行い、1との差分をとる
assert_differenceメソッドでのテストケース記述は、少しトリッキーな印象を受けるかもしれません。しかし、このように、ブロック処理の実行前後で所期の変化が起こったかどうかを検証するためのコードは、Controllerクラスが所期の働きをなしているかどうかの確認としてとても便利です。しっかりと確認しておきましょう。
続くassert_redirected_to hitokoto_path(assigns(:hitokoto))という行では、アクションの実行後に、指定のパスへのリダイレクトが行われることを検証しています。ここでは、リダイレクト先のパスとしてhitokoto_path(assigns(:hitokoto))が指定されています。
hitokoto_pathは「引数に指定されたModelクラスHitokotoに属するオブジェクト」を閲覧するためのパスを返すメソッドです。従って、ここではインスタンス変数@hitokotoに割り当てられたリソースを閲覧するためのパスへのリダイレクトが発生することを検証しています。
hitokotos_controller_test.rbでは、ほかにも各種アクションメソッドのテストケースが記述されていますが、ここまでに紹介したテストコードとほぼ同形態のテストとなっているので、これ以上の説明は割愛します。ここでは、先に検討したHitokotosControllerで実装する機能に基づき、機能テストコードを以下のように書き換えておくこととします。
require 'test_helper' class HitokotosControllerTest < ActionController::TestCase test "indexへのGETリクエストが成功し、hitokotos変数に「ひとこと」リストが割り当てられる" do get :index assert_response :success assert_not_nil assigns(:hitokotos) end test "newへのGETリクエストが成功し、users変数にユーザーのリストが割り当てられる" do get :new assert_response :success assert_not_nil assigns(:users) end test "createへのPOSTリクエストにより、Hitokotoのレコード数が1増加し、一覧画面に遷移する" do assert_difference('Hitokoto.count', 1) do post :create, :hitokoto => { :user_id => 1, :hitokoto => 'コーヒー' } end assert_redirected_to hitokotos_path end test "destroyへのDELETEリクエストにより、Hitokotoのレコード数が1減少し、一覧画面に遷移する" do assert_difference('Hitokoto.count', -1) do delete :destroy, :id => hitokotos(:banana).id end assert_redirected_to hitokotos_path end end
今回は、上記のとおり、index、new、create、destroyそれぞれのアクションメソッドを呼び出す際の機能テストを実装しました。テスト中で、前回までのModelクラスのユニットテストで作成したフィクスチャの読み込みも行っています。
2/3 |
Index | |
Controllerクラスの実装と機能テスト(前編) | |
Page1 Railsでよく使用されるアクションメソッド名 HitokotosControllerの実装 HitokotosControllerのアクションメソッド名 |
|
Page2 機能テストコードの実装 |
|
Page3 機能テストコードを実行してみる |
3rdRailによるRailsプログラミング入門 |
Ruby/Rails関連記事 |
プログラミングは人生だ まつもと ゆきひろのコーディング天国 ときにプログラミングはスポーツであり、ときにプログラミングは創造である。楽しいプログラミングは人生をより実りあるものにしてくれる |
|
生産性を向上させるRuby向け統合開発環境カタログ Ruby on Rails 2.0も強力サポート 生産性が高いと評判のプログラミング言語「Ruby」。統合開発環境を整えることで、さらに効率的なプログラミングが可能になる |
|
かんたんAjax開発をするためのRailsの基礎知識 Ruby on RailsのRJSでかんたんAjax開発(前編) 実はAjaxアプリケーション開発はあなたが思うよりも簡単です。まずはRuby on Railsの基礎知識から学びましょう |
|
Praggerとnetpbmで作る画像→AA変換ツール Rubyを使って何か面白いものを作ってみよう! 一般的な画像をアスキーアートに変換するツールを作ってみる。さらに出力にバリエーションを持たせてみよう |
|
コードリーディングを始めよう Railsコードリーディング〜scaffoldのその先へ〜(1) 優れたプログラマはコードを書くのと同じくらい、読みこなす。優れたコードを読むことで自身のスキルも上達するのだ |
|
- プログラムの実行はどのようにして行われるのか、Linuxカーネルのコードから探る (2017/7/20)
C言語の「Hello World!」プログラムで使われる、「printf()」「main()」関数の中身を、デバッガによる解析と逆アセンブル、ソースコード読解などのさまざまな側面から探る連載。最終回は、Linuxカーネルの中では、プログラムの起動時にはどのような処理が行われているのかを探る - エンジニアならC言語プログラムの終わりに呼び出されるexit()の中身分かってますよね? (2017/7/13)
C言語の「Hello World!」プログラムで使われる、「printf()」「main()」関数の中身を、デバッガによる解析と逆アセンブル、ソースコード読解などのさまざまな側面から探る連載。今回は、プログラムの終わりに呼び出されるexit()の中身を探る - VBAにおけるFileDialog操作の基本&ドライブの空き容量、ファイルのサイズやタイムスタンプの取得方法 (2017/7/10)
指定したドライブの空き容量、ファイルのタイムスタンプや属性を取得する方法、FileDialog/エクスプローラー操作の基本を紹介します - さらば残業! 面倒くさいエクセル業務を楽にする「Excel VBA」とは (2017/7/6)
日頃発生する“面倒くさい業務”。簡単なプログラミングで効率化できる可能性がある。本稿では、業務で使うことが多い「Microsoft Excel」で使えるVBAを紹介する。※ショートカットキー、アクセスキーの解説あり
|
|