2011年8月15日月曜日

Rails3を初歩から学ぶ #7 FactoryGirlを導入しよう

この一連のエントリは
Ruby on Rails 3 Tutorial: Learn Rails by Example (Addison-Wesley Professional Ruby Series)
で参考に学んだことを凝縮してお送りしています。



前回の予告通り、今回はUsersコントローラにshowアクションを定義します。
では例によってテストを書きましょう。
でも、待てよ、と。
showアクションは登録ユーザーの情報を表示するアクションですが検査時にその登録ユーザーはどうやって用意するんだ!?という問題があります。
もちろんUserオブジェクトを用意してDBに登録してやれば出来なくはないけれど、それってshowアクションの検査としてはあまり純粋じゃないし、不要なトラブルの元になりそうです。
こういうときにはテスト用のデータを用意するわけで、YAML形式でデータを用意するFixtureというものがRailsでは用意されています。
が、これはちょっと柔軟性に欠ける仕組みなのでRubyで試験データを用意できてしまうFactoryGirlなるものを導入してしまいましょう。
「Gemfile」に下記の赤字部分を追加します。

group :test do
  gem 'rspec'
  gem 'webrat'
  gem 'factory_girl_rails', '1.0'
end
バージョンを指定しないと最新版がインストールされますが、ここでは「1.0」を明示的に指定しています。最新版でも問題ないかもしれませんが、トラブったら1.0を指定してみましょう。
編集したら「bundle install」でインストールします。

インストールしたら「spec/factories.rb」というファイルを用意して以下のように編集します。

Factory.define :user do |user|
  user.name      "Son Gokuu"
  user.password  "foobar"
  user.password_confirmation  "foobar"
end
これでRSpecファイルから「Factory(:user)」とすれば名前が「Son Gokuu」でパスワードが「foobar」というユーザーがDBに登録済み、という状態になります。
早速つかってみましょう。

  describe "GET 'show'" do
    before(:each) do
      @user = Factory(:user)
    end
    it "should be successful" do
      get :show, :id => @user
      response.should be_success
    end
    it "正しいユーザーを表示していること" do
      get :show, :id => @user
      assigns(:user).should == @user
    end
    it "タイトルの検証" do
      get :show, :id => @user
      response.should have_selector("title", :content => @user.name)
    end
  end #GET 'show'
もうちょっとHTMLの中身を検査してもいいかもしれませんが、そこはお任せ。
とりあえず例題のshowアクションの検査としては上記のような感じになります。
beforeブロックは(eachを指定しているので)各検証コード(itブロック)を実行する前に毎回実行されます。ここで先ほど用意したFactoryGirlの機能を使ってテスト用のUserオブジェクトを取得しています。
RSpecでは1つの検証を終えるたびに環境をキレイにするので毎回DBへの登録が必要です。
また「assigns」メソッドはコントローラのインスタンス変数にアクセスするものです。
コントローラの@userがテストコードで生成した@userと一致することを確認しているわけです。
ではコントローラのshowアクションを用意しましょう。

  def show
    @user = User.find(params[:id])
    @title = @user.name
  end
ルート定義にあった「/users/:id」の「:id」に当たる部分を「params[:id]」で取得しています。Userテーブルに対して「Where id = X」で検索した結果を@userに格納している形になります。
さて次はviewを用意するんですが、「rails generate」でコントローラを生成するときにアクションまで指定していれば該当するviewファイルまで自動生成してくれます。が、今回のshowアクションは手動で追加しているのでviewファイルも手動で用意します。
「app/views/users/show.html.erb」を用意して以下のように編集します。
<h1><%= @user.name %></h1>
まあ、なんとも手抜きですが。。
ここまで出来たらテストを実行しましょう。全てパスするハズです。
ブラウザから動作確認する場合はDBが空なので(FactoryGirlはあくまでテスト環境のみで有効です)エラーになってしまいます。
「rails console」としてコンソールから無理矢理データをつくってしまいましょう。
※「rails console --sandbox」としないように。サンドボックス環境は終了時にロールバックされてしまいます
$rails console
>user = User.new(:name => "Son Gohan", :password => "foobar",
:password_confirmation => "foobar")
>user.save!
さあ、「rails server」でサーバーを起動したらブラウザから「http://localhost:3000/users/1」にアクセスしてみましょう。
デカデカと「Son Gohan」と出ていれば成功です。

0 件のコメント:

コメントを投稿