Ruby on Rails Tutorialのエッセンスを自分なりに整理してみる10
[Rails4.0] フォームの基本とStrongParametersを理解する
http://qiita.com/kidachi_/items/7c1a9b61dd1853d5a7dc
の続き。
Ruby on Rails Tutorial(chapter7)
http://railstutorial.jp/chapters/sign-up?version=4.0#code-after_save_tests
概要
ユーザ登録等、よくあるフォーム入力を実装した時、
いちいちブラウザから様々なパターンの値を入力してテストするのは大変。
Capybaraのシミュレート機能を使って解決する。
今回用いるCapybaraのメソッド
以下の2つ。
- fill_in
 - change
 
fill_in
フォームへの入力をシミュレートする。
例えば、
fill_in "Name", with: "Example User"
これでフィールド名"Name"のinput属性に"Example User"の入力をシミュレートしたことになる。
より具体的に、以下のようなユーザ情報入力フォームがあるとする。
    <%= form_for(@user) do |f| %>
      <%= render 'shared/error_messages' %>
      <%= f.label :name %>
      <%= f.text_field :name %>
      <%= f.label :email %>
      <%= f.text_field :email %>
      <%= f.label :password %>
      <%= f.password_field :password %>
      <%= f.label :password_confirmation, "Confirmation" %>
      <%= f.password_field :password_confirmation %>
      <%= f.submit "Create my account" , class: "btn btn-large btn-primary" %>
    <% end %>
この場合、以下のテストコードで各フィールドに対する値の入力が実現できる。
visit signup_path
fill_in "Name",         with: "Example User"
fill_in "Email",        with: "user@example.com"
fill_in "Password",     with: "foobar"
fill_in "Confirmation", with: "foobar"
change
オブジェクトとそのオブジェクトが持つメソッドを指定し、
その実行によって起きる変化を観測する。
click_buttonの後、User.countが1だけ変化する事を期待する例
expect do
  click_button "Create my account"
end.to change(User, :count).by(1)
- オブジェクト(User)とシンボル(:count)を引数に取り、シンボルに該当する名前のメソッドを呼び出す。
 - 
expect do~end.toの後ろについて、ブロック内が実行される前後での変化を比較する。 
実際のテストコード
上記2つのメソッドを用いて、
- ユーザ登録ページ(signup)に訪れ
 - フォームに何らかの値を入力し(もしくは入力しないで)、
 - "Create my account"ボタンを押下
 
したケースをシミュレートするテストコード
require 'spec_helper'
describe "User pages" do
  subject { page }
  describe "signup" do
    before { visit signup_path }
    let(:submit) { "Create my account" }
    # 不正な値が入力された(正確には、何も入力されていない)ケース
    describe "with invalid information" do
      it "should not create a user" do
        #click_buttonの後、User.countが変化しない事を期待
        expect { click_button submit }.not_to change(User, :count)
      end
    end
    # 正しい値が入力されたケース
    describe "with valid information" do
      before do
        fill_in "Name",         with: "Example User"
        fill_in "Email",        with: "user@example.com"
        fill_in "Password",     with: "foobar"
        fill_in "Confirmation", with: "foobar"
      end
      it "should create a user" do
        #click_buttonの後、User.countが1だけ変化する事を期待
        expect { click_button submit }.to change(User, :count).by(1)
      end
    end
  end
end
便利!
関連
RSpecの基本等については以下も参照ください。
[Rails] RSpecによるBDD(振舞駆動開発)の基本 [SporkとGuardも]
http://qiita.com/kidachi_/items/cb8910eb74e924456df9
[Rails] RSpecのリファクタリング
http://qiita.com/kidachi_/items/ec184deb106e4e5c90c3