Monday, October 26, 2009

フィードバックが得られない文化を維持していくことは難しい

[社会][web&リアル]文化の地域格差は人の格差か?— はてブついでに覚書。
文化の発信はどこからでもできるが,文化は中央に集約してしまう。そりゃそうだ。観客の数が違う。数が多いとフィードバックが多い。文化は発信だけでなく,反応もなければ成立しない。
例えば,地元鹿角市には正月2日に大日霊貴神社(大日堂,だいにちどうといった方が地元では通じるだろう。)で舞を奉納している。うちの集落谷内では,「五大尊舞」という演目が伝承されている。この日は県内の報道機関やアマチュアカメラマンが一同に集り,カメラのフラッシュがたかれる。
参考 大日堂舞楽(鹿角市)がユネスコ無形文化遺産の「代表一覧表」に記載されました
伝聞のように書いてあるのは,実は私は全く知らない。実は集落の人,特に同年代の方々を全く知らないのだ。自分が参加していないのが悪いんだろうと言われるが,引きこもり的な資質もあり中々進んでいけない。集落の方々が共有して持っている少年青年期に体験したことを私は全くしていない。理由は簡単。父が転勤族のため,小・中・高校と全て違うところで生活してきたからだ。
最初に戻ろう。文化の発信は1人でもできる。しかし,必ずしもフィードバックが得られるとは限らない。まだ東京の方が可能性がある。
文化の格差というよりも,文化を共有できる関係を求めるのが人間の性だと思う。San Jose近郊のBay areaに集まる人や,東京に集まる人。などなど。

Tuesday, October 13, 2009

Add new user (2) - Reading Tracks (5)

今日の課題


        unless User.no_users_yet? || (@user && @user.is_admin?)
          @page_title = "No signups"
          @admin_email = User.find_admin.preference.admin_email
          render :action => "nosignup", :layout => "login"
          return
        end
Userが登録されているにもかかわらず,admin以外のユーザが登録しようとしても失敗させるためのケース。

        user = User.new(params['user'])
で,モデルUserのインスタンスを生成し,その次の評価で,作成するインスタンスのvalid性を評価している。

        unless user.valid?
          session['new_user'] = user
          redirect_to :action => 'new'
          return
        end
validでないUserインスタンスならば,"/user/new" にリダイレクトさせて,その際にerror内容を表示させるのだろう。

        first_user_signing_up = User.no_users_yet?
        user.is_admin = true if first_user_signing_up
ここで,最初のuser登録かチェックしている。つまり,最初に登録されるユーザは必ずadmin権限を持つようになっている。

        if user.save
          @user = User.authenticate(user.login, params['user']['password'])
          @user.create_preference
          @user.save
          session['user_id'] = @user.id if first_user_signing_up
          notify :notice, "Signup successful for user #{@user.login}."
          redirect_back_or_home
        end
        return
最後に,新しく生成したインスタンスが保存できるのならば,redirect_back_or_home され,処理を終える。

おもしろい。このまま,tracks Applicationの実装を読み進めていこう。それと並行してRails applicationの試作を行ってみたい。

Monday, October 12, 2009

Add new user - Reading Tracks (4)

今日の課題

ユーザ登録はどのようにやっているのか?具体的には,


192.168.1.102 - - [08/Oct/2009:22:52:51 JST] "POST /users HTTP/1.1" 302 92
http://192.168.1.101:3000/users/new -> /users
ここで,どんな処理をしているのか?
早速,user_controller.rb の該当するコードを参照してみる。

  # Example usage: curl -H 'Accept: application/xml' -H 'Content-Type: application/xml'
  #               -u admin:up2n0g00d
  #               -d '<request><login>username</login><password>abc123</password></request>'
  #               http://our.tracks.host/users
  #
  # POST /users
  # POST /users.xml
  def create
    if params['exception']
      render_failure "Expected post format is valid xml like so: <request><login>username</login><password>abc123</password></request>."
      return
    end
    respond_to do |format|
      format.html do
        unless User.no_users_yet? || (@user && @user.is_admin?)
          @page_title = "No signups"
          @admin_email = User.find_admin.preference.admin_email
          render :action => "nosignup", :layout => "login"
          return
        end
        
        user = User.new(params['user'])
        unless user.valid?
          session['new_user'] = user
          redirect_to :action => 'new'
          return
        end

        first_user_signing_up = User.no_users_yet?
        user.is_admin = true if first_user_signing_up
        if user.save
          @user = User.authenticate(user.login, params['user']['password'])
          @user.create_preference
          @user.save
          session['user_id'] = @user.id if first_user_signing_up
          notify :notice, "Signup successful for user #{@user.login}."
          redirect_back_or_home
        end
        return
      end
      format.xml do
        unless User.find_by_id_and_is_admin(session['user_id'], true)
          render :text => "401 Unauthorized: Only admin users are allowed access to this function.", :status => 401
          return
        end
        unless check_create_user_params
          render_failure "Expected post format is valid xml like so: <request><login>username</login><password>abc123</password></request>."
          return
        end
        user = User.new(params[:request])
        user.password_confirmation = params[:request][:password]
        if user.save
          render :text => "User created.", :status => 200
        else
          render_failure user.errors.to_xml
        end
        return
      end
    end
  end  
まず最初の例外処理を見てみる。

    if params['exception']
      render_failure "Expected post format is valid xml like so: <request><login>username</login><password>abc123</password></request>."
      return
    end
想定外のXML文書が来たかどうかだと思う。想定外かどうか判断するには,モデルuserを参照するのだろう。validates_presence_of には,:login と :password があり,:login は 3文字以上80文字以下などなどと制限を設けている。そして失敗したら,render_failure で失敗理由を明示し,元に戻っている。
実際のテストコードでも,このような内容のテストが行なわれている。test/functional/users_controller_test.rb の以下のテストだ。

  def test_create_with_invalid_password_does_not_add_a_new_user
    login_as :admin_user
    assert_no_difference(User, :count) do
      post :create, :user => {:login => 'newbie', :password => '', :password_confirmation => ''}
    end
  end
  
  def test_create_with_invalid_password_redirects_to_new_user_page
    login_as :admin_user
    post :create, :user => {:login => 'newbie', :password => '', :password_confirmation => ''}
    assert_redirected_to :controller => 'users', :action => 'new'    
  end
  
  def test_create_with_invalid_login_does_not_add_a_new_user
    login_as :admin_user
    post :create, :user => {:login => 'n', :password => 'newbiepass', :password_confirmation => 'newbiepass'}
    assert_redirected_to :controller => 'users', :action => 'new'    
  end
  
  def test_create_with_invalid_login_redirects_to_new_user_page
    login_as :admin_user
    post :create, :user => {:login => 'n', :password => 'newbiepass', :password_confirmation => 'newbiepass'}
    assert_redirected_to :controller => 'users', :action => 'new'    
  end
なるほど,最初のテストではinvalidなpasswordを持つuserをUserに追加させていない。他の3つは,invalidな:login,:password を持つuserの作成に対するrequestに対して, /users/new に redirect されているかどうかをテストしている。(警告メッセージが出ているのかどうかテストするにはどうすればいいのだろうか。)
次の行からは,
respond_to do |format|
と始まっているように,responseを作成している箇所であることを確認して,ここまでとする。早速以下の処理内容を理解できないので,じっくりと把握していきたい。

        unless User.no_users_yet? || (@user && @user.is_admin?)
          @page_title = "No signups"
          @admin_email = User.find_admin.preference.admin_email
          render :action => "nosignup", :layout => "login"
          return
        end

HTTP POST Method - Reading Track (3)

今日の課題

POSTの内容はどうなっているのか?誰がPOSTの内容をXML文書に成形しているのか?


<request><login>username</login><password>abc123<password></request>

POSTリクエストを送信したときのパケットをキャプチャしてみた。TCP payloadの内容を以下に記す(passwordの箇所は"password"でマスクした)。


POST /login HTTP/1.1
Host: 192.168.1.101:3000
User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.3) Gecko/20091007 Ubuntu/9.10 (karmic) Firefox/3.5.3 GTB5
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-2022-JP,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://192.168.1.101:3000/login
Cookie: preferred_auth=database; tracks_login=admin; _tracks_session_id=e22a17f51266e7fa3b30fb6cd3def1fb
Content-Type: application/x-www-form-urlencoded
Content-Length: 139

authenticity_token=2fc78f9b3f11d9447cdc5719f19742bdfe9b531f&user_login=admin&user_password=password&user_noexpiry=on&login=Sign+In+%C2%BB

Studying HTTPは,HTTP/1.1 Post Methodについて解説していただいている。そこを参照すると,Content-Type: application/x-www-form-urlencoded はエンテティボディのメディアタイプとして一般的に利用されているタイプの一つで,今回のUser-Agent (Firefox 3.5.3) は,この方式でエンティティを送信しているものと考えられる。このように,規格があるのならば,このようなRequestパケットを受信したRailsアプリケーションがurlencodedなデータから,validなXML-documentを生成するのは簡単だろう。他のブラウザではどのような形式で送信するかわからないが,そこのところはRailsでwrapperしているものと考えればいいのだろう。

Rails Application - Reading Tracks (2)

users_controller.rb - Tracks reading.

user_controller.rb

Track applicationでユーザー(admin)を登録した時のコンソール出力から何が起きているか確認してみる。
まず,user_controller.rb のアクション new の内容を確認する。

  # GET /users/new
  def new
    if User.no_users_yet?
      @page_title = "TRACKS::Sign up as the admin user"
      @heading = "Welcome to TRACKS. To get started, please create an admin account:"
      @user = get_new_user
    elsif @user && @user.is_admin?
      @page_title = "TRACKS::Sign up a new user"
      @heading = "Sign up a new user:"
      @user = get_new_user
    else # all other situations (i.e. a non-admin is logged in, or no one is logged in, but we have some users)
      @page_title = "TRACKS::No signups"
      @admin_email = User.find_admin.preference.admin_email
      render :action => "nosignup", :layout => "login"
      return
    end
    render :layout => "login"
  end
userがまだ未定義なので,Title と headline,Userモデルのインスタンスを確保している。そして,最後にある render :layout => "login" が view の提供のキーとなるだろう。ActionController::Baseのrenderメソッドを確認すると,"login"というカスタムレイアウトを用いれ,response bodyを作成していることがわかる。ここで,app/views/layout/login.html.erb の中身を見てみる。
@page_title というのが出てきた。先ほど指定した @page_title が埋めこまれている。おそらく <%= render :partial => "shared/footer" %> は共通のfooterを埋めこんでいるのだろう。
さて,<%= yield %> は何ものか?これはActionController::Layoutのクラスメソッドの説明を読んで考えてみると,どうやらtitleとかfooterは共通にしたいけど,login 画面は個別のviewを埋めこみたいと考えているのだろうか。ここで,"/users/new" リクエストでアクセスしてきたことを思いだす。app/views/users/new.html.erb が定義されてあった。 ここでユーザーAccount Signupのviewを生成しているのだなと確認できる。
さて,submitボタンを押したときに,コンソール画面には以下の内容が表示されている。

192.168.1.102 - - [08/Oct/2009:22:52:51 JST] "POST /users HTTP/1.1" 302 92
http://192.168.1.101:3000/users/new -> /users
再び users_controller.rb に戻ろう。"POST /users" リクエストなので,create メソッドが実行される。create メソッドの内容は以下の通り。

  # Example usage: curl -H 'Accept: application/xml' -H 'Content-Type: application/xml'
  #               -u admin:up2n0g00d
  #               -d 'usernameabc123'
  #               http://our.tracks.host/users
  #
  # POST /users
  # POST /users.xml
  def create
    if params['exception']
      render_failure "Expected post format is valid xml like so: usernameabc123."
      return
    end
    respond_to do |format|
      format.html do
        unless User.no_users_yet? || (@user && @user.is_admin?)
          @page_title = "No signups"
          @admin_email = User.find_admin.preference.admin_email
          render :action => "nosignup", :layout => "login"
          return
        end
        
        user = User.new(params['user'])
        unless user.valid?
          session['new_user'] = user
          redirect_to :action => 'new'
          return
        end

        first_user_signing_up = User.no_users_yet?
        user.is_admin = true if first_user_signing_up
        if user.save
          @user = User.authenticate(user.login, params['user']['password'])
          @user.create_preference
          @user.save
          session['user_id'] = @user.id if first_user_signing_up
          notify :notice, "Signup successful for user #{@user.login}."
          redirect_back_or_home
        end
        return
      end
      format.xml do
        unless User.find_by_id_and_is_admin(session['user_id'], true)
          render :text => "401 Unauthorized: Only admin users are allowed access to this function.", :status => 401
          return
        end
        unless check_create_user_params
          render_failure "Expected post format is valid xml like so: usernameabc123."
          return
        end
        user = User.new(params[:request])
        user.password_confirmation = params[:request][:password]
        if user.save
          render :text => "User created.", :status => 200
        else
          render_failure user.errors.to_xml
        end
        return
      end
    end
  end  

Signup » を押すと,POSTリクエストが生成され,Rails アプリケーションには

<request><login>username</login><password>abc123</password></request>
とvalidなXML形式がcontrollerに送られている模様。誰がXML形式に成形しているのだろうか?

Thursday, October 08, 2009

Rails Application - Reading Tracks (1)

Rails Application Tracks を読む

ここでは,Rails Application, Tracksの振舞いを見てみる。
Tracks を動かすのは簡単だ。自分は Rails 2.3.3 の環境を構築して,SQLite3,libsqlite3-ruby をインストールすれば準備完了。Download ページから 1.7 release を展開して,rake db:migdate を実行した後,server を実行する(databaseのconfigは用意されてある)。
起動してみて,webブラウザでアクセスすると,コンソールに以下の内容が表示される。


192.168.1.102 - - [08/Oct/2009:21:57:59 JST] "GET / HTTP/1.1" 302 97
- -> /
192.168.1.102 - - [08/Oct/2009:21:57:59 JST] "GET /login HTTP/1.1" 302 101
- -> /login
192.168.1.102 - - [08/Oct/2009:21:58:00 JST] "GET /users/new HTTP/1.1" 200 2523
- -> /users/new
どうやら login controller を経由して,users_controller の new アクションを実行している模様。 config/routes.rb の内容を確認してみると,

ActionController::Routing::Routes.draw do |map|
  map.with_options :controller => 'login' do |login|
    login.login 'login', :action => 'login'
    login.formatted_login 'login.:format', :action => 'login'
    login.logout 'logout', :action => 'logout'
    login.formatted_logout 'logout.:format', :action => 'logout'
  end
  # snip 
とあるので,login controller の login action を呼びだしている模様。login.login とか login.formatted_login とかが何を表現しているのかがよくわからない。これは "/login" や "login.m" というリクエストに対して名前をつけたと考えていいのだろうか?
このことを確認するため,ユーザ登録後に "/login","/login.m","/login.xml" というリクエストを発行した。login_controller の login method の最後の方に,こんな表示がある。

      respond_to do |format|
        format.html
        format.m   { render :action => 'login_mobile.html.erb', :layout => 'mobile' }
従って最後の "/login.xml" は xml 形式のrespondが定義されていないので,何も表示されない。実際に "/login.xml" では何も表示されない。また "/login.m" ではいかにも携帯電話用のログイン画面が表示された。
さて,login_controller.rb の内容に戻ってみる。

  def login
    if openid_enabled? && using_open_id?
      login_openid
    else
      @page_title = "TRACKS::Login"
      case request.method
      # snip
        when :get
          if User.no_users_yet?
            redirect_to :controller => 'users', :action => 'new'
            return
          end
      end
      # snip
    end
  end
とあるので,ユーザを未登録の場合,users controller の action new へ redirect されているのがわかる。

次にユーザ(admin)を登録してみる。コンソール出力は以下の通り。


192.168.1.102 - - [08/Oct/2009:22:52:51 JST] "POST /users HTTP/1.1" 302 92
http://192.168.1.101:3000/users/new -> /users
192.168.1.102 - - [08/Oct/2009:22:52:52 JST] "GET / HTTP/1.1" 200 10825
http://192.168.1.101:3000/users/new -> /
192.168.1.102 - - [08/Oct/2009:22:53:01 JST] "GET /stylesheets/cache/bundle.css?1255009973 HTTP/1.1" 200 29449
http://192.168.1.101:3000/ -> /stylesheets/cache/bundle.css?1255009973
192.168.1.102 - - [08/Oct/2009:22:53:01 JST] "GET /behaviours/index.js HTTP/1.1" 304 0
http://192.168.1.101:3000/ -> /behaviours/index.js
192.168.1.102 - - [08/Oct/2009:22:53:01 JST] "GET /javascripts/cache/bundle.js?1255009981 HTTP/1.1" 200 247440
http://192.168.1.101:3000/ -> /javascripts/cache/bundle.js?1255009981
次から users_controller.rb の内容を追ってみようと思う。

Rails Integration Test (1)

A Guide to Testing Rails Applications

5. Integration Testing

Integration テスト: (複数の)コントローラ間の通信をテストすること。important work flowsをテストするのに使われる。
RailsにはIntegrationテスト用のスケルトンコード作成機能が備わっている。


% script/generate integration_test user_flows
      exists  test/integration/
      create  test/integration/user_flows_test.rb
内容は,こんな感じ。

require 'test_helper'

class UserFlowsTest < ActionController::IntegrationTest
  fixtures :all

  # Replace this with your real tests.
  test "the truth" do
    assert true
  end
end
ここで,fixturesというのが出てきた。

5.1 Helpers Available for Integration Tests

どんな helper が使えるのかという内容。リンク先のテーブル参照。

ここまで読んで,その後もざっと流し読みしたが,自分の中のRailsやTDDについてのイメージがまだ浮かんでこないので,ここで実際のアプリケーションに立ち入って理解していきたいと思う。

Monday, October 05, 2009

Rails Functional Test (2)

A Guide to Testing Rails Applications

昨日の復習


  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

というテストコードを書いた。最初の"post :create, :post => { :title => 'Hi', :body => 'This is my first post.' }" はpostコントローラにcreate アクションを実行。":post" symbol にpost controllerのcreate actionに対する引数を与えた。(パラメータは{ :title => 'Hi', :body => 'This is my first post.' })
次のassert文 "assert_redirected_to post_path(assigns(:post))" 。よくわからないが,"format.html { redirect_to(@post) }" に関連したテストなのだろうか?
最後のassert文,"assert_equal 'Post was successfully created.', flash[:notice]" で,flash[:notice]に "Post was successfully created" が渡されているかどうかをテスト。post_controller.rb を見ると,flash[:notice] に "Post was successfully created" が引き渡されていた。

  def create
    @post = Post.new(params[:post])

    respond_to do |format|
      if @post.save
        flash[:notice] = 'Post was successfully created.'
        format.html { redirect_to(@post) }
        format.xml  { render :xml => @post, :status => :created, :location => @post }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @post.errors, :status => :unprocessable_entity }

続き。

4.6 Testing Views

viewのテストとして,key HTML elementsの存在やコンテンツに対するassertingをすることによって,viewのテストを行う。
"assert_select" を使うことで,simpleだけどpowerfulなsyntaxを使うことができる。
assert_selectの形式:

assert_select (selecter, [equality], [message]) ensures that the equality condition is met on the selected elements through the sector. The selector may be a CSS selector expresion (String), an expression with substitution valutes, or an HTML::Selector object.
assert_select (element, selecter, [equality], [message]) ensures that the equality condition is met on all the selected elements through the selector starting from the element (instance of HTML::Node) and its descendants.

  assert_select 'title', "Welcome to Rails Testing Guide"
あまり用途がわからない。他の用法等を参照してみる。

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

Saturday, October 03, 2009

Rails Unit Test

これまでの流れ。 A Guide to Testing Rails Applicationsを読んでいる。

確認


  test "post should not save without title" do
    post = Post.new
    assert !post.save, "Saved the post without a title"
  end

というテストを書いたので,今度は

  test "post can save with title" do
    post = Post.new
    post.title = "Test Title"
    assert post.save, "Saved the post with a title"
  end

というのを書いてみたが, post.title = "Test Title" で怒られる。どう記述すればいいのか。

3.3 What to Include in Your Unit Tests

続き
Unit Testに何を含めればいいのか?

Ideally you would like to include a test for everything which could possibly break. It’s a good practice to have at least one test for each of your validations and at least one test for every method in your model. 理想的にいえば,起こりえる全ての事に大してテストしたい。全てのvalidationに対して少なくとも一つのテストと,全てのメソッドに対しても少くても一つ以上のテストを作成するのが good practice である。
メソッドに対するテストと書いてあるが,具体的にどんなメソッドテストを書くのだろうか?

3.4 Assertions Available

3.5 Rails Specific Assertions

どんなassert式を書けるか。Rails特有のassertionは? リンク先の表を見るのがいい。