rspecの基礎リファレンス

rspecを勉強するにあたって、自分なりにメモをまとめてみました。
そんなメモを公開。


★使い方
■rspecファイル生成
  ・rails g rspec:model user
■実行
  ・bundle exec rspec -fd spec/models/user_spec.rb 
    #fdオプションは仕様書風の出力をする

★基本構造
■describe 
  ・テストのグループ化
  ・describeの中にdescribeをネスト化
  ・クラス単位などグループ化する時に利用
  ・例 describe '四則演算' do

■context
  ・describeとほぼ同じ
  ・クラス単位ではなく状態単位で利用
  ・例 context '12歳以下の場合' do
	■befor
	  ・前提条件
	  ・例 @params = { name: 'たろう' }

	■it テストケース(exapmle) 
	  ・describeの中に記載 複数化
	  ・例 it '1 + 1 は 2 になること' do
	  ・exampleとspecifyはitのエイリアス(自然な英文を作るため)

		■expect 期待(合格条件) 
		  ・itの中に記載 複数化
		  ・例 expect(1 + 1).to eq 2

★テクニック
■let
  ・変数を置き換えるテクニック
  ・let(:foo) { ... } のように書くと、 { ... } の中の値が foo として参照できる
  例 let(:user) { User.new(params) }
     let(:params) { { name: 'たろう', age: age } }
     let(:age) { 13 }
  ・以下と同じ意味
    @params = { name: 'たろう' }
  ・遅延評価されるためcontext内で異なる部分だけcontextの中で定義すればOK

■subjct
  ・テスト対象のオブジェクトをまとめる
  例 subject { user.greet }
     ※userオブジェクトのgreetメソッドを共通してテストする場合
  ・is_expectedでsubjectを呼び出す。
  例 is_expected.to eq 'ぼくはたろうだよ。


■shared_examples,it_behaves_like 
  ・exampleの再利用
  ・shared_examplesに再利用したいexapmleを記載する。
  例 shared_examples '子どものあいさつ' do
      it { is_expected.to eq 'ぼくはたろうだよ。' }
     end
  ・it_behaves_likeでshared_examplesを呼び出し
  例 context '0歳の場合' do
      let(:age) { 0 }
      it_behaves_like '子どものあいさつ'
    end
  ・shared_examples 'foo' do ... end で再利用したいexampleを定義し、 it_behaves_like 'foo' で定義したexampleを呼び出す

■shared_context,include_context
  ・contextの再利用
  ・shared_examples,it_behaves_likeと同じ
  例 shared_context '12歳の場合' do
      let(:age) { 12 }
     end
     ・・・
     context '12歳以下の場合' do
      include_context '12歳の場合'
      it { is_expected.to eq 'ぼくはたろうだよ。' }
     end

■let!
  ・即時評価のlet
  ・以下のパターン回避
  describe Blog do
   let(:blog) { Blog.create(title: 'RSpec必勝法', content: 'あとで書く') }
   it 'ブログの取得ができること' do
    expect(Blog.first).to eq blog
    #ここのBlog.firstが呼び出された時点ではblogは評価されないためエラーになる。
   end
  end

■pending
  ・以降のテストを保留する
  ・ただし内部的にはテストは実行されて、逆にすべて合格すると怒られる。
  例 pending 'この先はなぜかテストが失敗するのであとで直す'
  ・中身のないitもpendingとしてマークされる

■skip
  ・問答無用でテストの実行を止める
  例 skip 'とりあえずここで実行を保留'
  ・xit,xspecify,xexample  example全体をskip
  例 xit '実行したくないテスト' do
  ・xdescribe,xcontext グループ全体をskip
  xdescribe '四則演算' do

★マッチャ
■to
  ・「～であること」
  例 expect(1 + 2).to eq 3

■not_to,to_not
  ・「～ではないこと」
  例 expect(1 + 2).not_to eq 1
■eq
  ・「等しい」
  例 expect(1 + 2).to eq 3
  ・true/falseは厳密にチェックされる。1はtrueではないし、nilはfalseでない。

■be_xxx (predicateマッチャ)
  ・empty? のようにメソッド名が「?」で終わり、戻り値が true / false になるメソッドを be_empty のような形式で検証
  例 expect([]).to be_empty

■be_truthy / be_falsey
  ・戻り値として true / false を返すメソッドを検証
  例 expect(user.save).to be_truthy
     #userのデータを保存できればtrueが返ってくるはず。
  ・be_truthy / be_falseyはtrueっぽい値、falseっぽい値かどうかを確認する。

■change
  ・「X すると Y が A から B に変わることを期待する」
  例 expect{ X }.to change{ Y }.from(A).to(B)
  例 expect{ user.destroy }.to change{ Blog.count }.by(-1)
     #userを削除すると、userが書いたblogも削除されること

■配列 + include
  ・「配列に～が含まれていること」
  例 x = [1, 2, 3]
     # 1が含まれていることを検証する
     expect(x).to include 1
     # 1と3が含まれていることを検証する 
     expect(x).to include 1, 3

■raise_error
  ・「エラーが起きること」
  例 expect{ 1 / 0 }.to raise_error ZeroDivisionError

■be_within + of
  ・「ある程度のゆらぎの範囲であること」
  ・between的な
  例 expect(probability).to be_within(1.0).of(25.0)
     #24から26であること


★モック(スタブ)


★modelスペックに含める内容
  ・有効な属性が渡された場合、モデルのcreateメソッドが正常に完了すること。
  ・バリデーションを失敗させるデータがあれば、正常に完了しないこと。
  ・クラスメソッドとインスタンスメソッドが期待通りに動作すること。
  例 describe Article do
       #titleとcontentが入っていれば有効であること
       it "is valid with title and content" do
         article = Article.new(
           title: 'hoge',
           content: 'hogehoge'
         )
         expect(article).to be_valid
       end
     end

★controllerスペック
  ・http://biboroku.megaya.net/entry/2015/02/01/224949

★Viewスペック
  ・フィーチャスペック
  ・capybara


★Factory Girl(テストデータ生成)
  ・factoriesディレクトを作成。
  例 /spec/factories/article.rbに以下のように記載する。
       FactoryGirl.define do
         factory :contact do
           title: 'hoge'
           content: 'hogehoge'
         end
       end
  ・Factory Girlを利用するとき
  例 /spec/models/article_spec.rbに以下のように記載する。
        #省略
       describe Article do
         #titleとcontentが入っていれば有効であること
         it "is valid with title and content" do
           article = FactoryGirl.build(:article)
           expect(article).to be_valid
         end
       end
★Faker (テストデータ自動生成)
  例/spec/factories/article.rb
      require 'faker'

      FactoryGirl.define do
        factory :contact do
          title: { Faker::Lorem.sentence }
          content: { Faker::Lorem.paragraph }
        end
      end
 ・http://www.rubydoc.info/github/stympy/faker/master/frames
 ・http://qiita.com/kyanny/items/00ef3727c7738f2cc26c


以下の記事を参考に作成しました。
使えるRSpec入門・その1「RSpecの基本的な構文や便利な機能を理解する」
http://qiita.com/jnchito/items/42193d066bd61c740612

使えるRSpec入門・その2「使用頻度の高いマッチャを使いこなす」
http://qiita.com/jnchito/items/2e79a1abe7cd8214caa5