Sunday, October 04, 2009

Rails Functional Test (1)

A Guide to Testing Rails ApplicationsFunctional Tests for Your Controllersから再開。

4. Functional Tests for Your Controllers

Rails における,functional test: controller単体の様々なアクションをテストすること。Controllersはimcoming web-requestをアプリケーションに受け渡し,その結果rendered viewを返答する。

4.1 What to Include in your Functional Tests

テストすべき項目
  • was the web request successful? (日本語では何といえばいい?成功したweb request?ちゃんとしたweb requestであるか?)
  • was the user redirected to the right page? 正しいページにリダイレクトされたか?
  • was the user successfully authenticated? (ユーザーはちゃんと認証されたか?)
  • was the correct object stored in the response template? (正しいオケクトがレスポンステンプレートの中に記録されたか?)
  • was the appropriate message displayed to the user in the view? (適切なメッセージがユーザにview表示されたか?)
以前,ScaffoldでPostモデルを作成したので,その際に作成したコントローラのコードや機能をここではテストする。test/functional ディレクトリにテスト posts_controller_test.rb があるのでそれを参照してみる。
tutorialでは test_should_get_index というメソッドが定義されているが,ここでは

  test "should get index" do
    get :index
    assert_response :success
    assert_not_nil assigns(:posts)
  end

となっているので今回も,これを見てみる。
"should get index"テストでは,Railsは "index" アクションを要求して, request が成功したかどうかを,そして更に妥当な posts インスタンス変数を割りあてているかどうかテストを確認している。
"get" メソッドはweb requestを発行して,結果をレスポンスに反映させている。It (="get" method) accepts 4 arguments:
  • リクエストするコントローラのアクション。文字列,もしくはsymbol形式で与える。
  • (Optional)アクションに引き渡すリクエストパラメータのオプショナルハッシュ (eg. クエリー文字列やポスト変数)。
  • (Optional)リクエストに沿った内容のセッション変数のハッシュ
  • (Optional)フラッシュ値(メッセージ)
例題。:show アクションを呼びだす。その際,"12"というidをパラメータとして与え,セッションにおける"user_id"を5と指定する。

  get(:show, {'id' => "12"}, {'user_id' => 5})
例題。:view アクションを呼びだす。その際,"12"というidをパラメータとして与える。セッションは確立されないとするが,フラッシュメッセージが添えられている。

  get(:view, {'id' => "12"}, nil, {'message' => 'booya!'))
ここで先に進む前に,Post モデルに "validates_presence_of :title" を追加したことを思い出す。
If you try running test_should_create_post test from posts_controller_test.rb it will fail on account of the newly added model level validation and rightly so.
と書いてあるように,Testがパスできるように test_should_create_post に手を加える。

  test "should create post" do
    assert_difference('Post.count') do
      post :create, :post => { :title => 'Some title' }
    end

    assert_redirected_to post_path(assigns(:post))
  end

実際にfunctional testを実行してみた。
変更前

/home/abekatsu/webroot/TestingRails% rake test:functionals
(in /home/abekatsu/webroot/TestingRails)
/usr/bin/ruby1.8 -I"lib:test" "/home/abekatsu/.gem/ruby/1.8/gems/rake-0.8.7/lib/rake/rake_test_loader.rb" "test/functional/posts_controller_test.rb" 
Loaded suite /home/abekatsu/.gem/ruby/1.8/gems/rake-0.8.7/lib/rake/rake_test_loader
Started
F......
Finished in 0.236084 seconds.

  1) Failure:
test_should_create_post(PostsControllerTest) [/test/functional/posts_controller_test.rb:16]:
"Post.count" didn't change by 1.
<3> expected but was
<2>.

7 tests, 9 assertions, 1 failures, 0 errors
rake aborted!
Command failed with status (1): [/usr/bin/ruby1.8 -I"lib:test" "/home/abeka..."]
(See full trace by running task with --trace)
変更後

/home/abekatsu/webroot/TestingRails% rake test:functionals
(in /home/abekatsu/webroot/TestingRails)
/usr/bin/ruby1.8 -I"lib:test" "/home/abekatsu/.gem/ruby/1.8/gems/rake-0.8.7/lib/rake/rake_test_loader.rb" "test/functional/posts_controller_test.rb" 
Loaded suite /home/abekatsu/.gem/ruby/1.8/gems/rake-0.8.7/lib/rake/rake_test_loader
Started
.......
Finished in 0.23919 seconds.

7 tests, 10 assertions, 0 failures, 0 errors

4.2 Available Request Types for Functional Tests

Railsのfunctional テストでサポートされているリクエストタイプ:
  • get
  • post
  • put
  • head
  • delete
get, postでほとんどのテストが書けてしまうだろうとある。

4.3 The Four Hashes of the Apocalypse

先程の5つのメソッドでリクエストが作成されると,次の4つのタイプのハッシュオブジェクトを使用できる。
  • assigns - Any objects that are stored as instance variables in actions for use in views.
  • cookies - Any cookies that are set.
  • flash - Any objects living in the flash
  • session - Any objected in session variables.
使用例

flash["gordon"]           flash[:gordon]
session["shmession"]      session[:shmession]
cookies["are_good_for_u"] cookies[:are_good_for_u]

# Because you can't use assigns[:something] for historical reasons:
assigns["something"]      assigns(:something) 

4.4 Instance Variables Available

functional testに次の3つのインスタンス変数にアクセスできる。
  • @controller – The controller processing the request
  • @request – The request
  • @response – The response

4.5 A Fuller Functional Test Example


  test "should create post" do
    assert_difference('Post.count') do
      post :create, :post => { :title => 'Hi', :body => 'This is my first post.' }
    end

    assert_redirected_to post_path(assigns(:post))
    assert_equal 'Post was successfully created.', flash[:notice] 
  end

No comments:

There was an error in this gadget