Ruby
Rails
RSpec
RubyOnRails

久しくRspecでテスト書いてなかったので自分用に復習メモ。

やっぱりSir.JunichiItoの記事がわかりやすすぎるので、説明やコードなどはそちらを参照。
https://qiita.com/jnchito/items/42193d066bd61c740612

キーワード

  • describe テスト対象
  • context ケース分け
  • it 振る舞いの説明
  • expect(振る舞い).matcher(期待する出力)
  • before 前処理(テストで必要な変数などの定義)
  • let 遅延評価される(必要になって初めて呼ばれる)変数を定義
  • let! 遅延評価したくない時。
  • pending 保留

ちょい応用
- shared_examples 'hoge' do と it_behaves_like('hoge')で期待する振る舞いをDRYに
- shared_context 'fuga' do と include_context('fuga')で必要な前処理をケースごとで定義しDRYに

マッチャー
https://qiita.com/jnchito/items/2e79a1abe7cd8214caa5

コントローラーとか実践的なテスト
https://qiita.com/Morinikiz/items/cf179583c2c5d2e24c3c

ポイント

letは遅延評価される。
letの遅延評価でnilエラーとか出る場合、let!を使う必要があったり。
テストは読みやすさが大事

コードを拝借。これに基本のエッセンスは詰まってる。

user_spec.rb
describe User do
  describe '#greet' do
    let(:user) { User.new(name: 'たろう', age: age) }
    subject { user.greet } #テスト対象のオブジェクトをDRYに
    context '12歳以下の場合' do
      let(:age) { 12 }
      it { is_expected.to eq 'ぼくはたろうだよ。' }
    end
    context '13歳以上の場合' do
      let(:age) { 13 }
      it { is_expected.to eq '僕はたろうです。' }
    end
  end
end

shared_examplesの例

describe User do
  describe '#greet' do
    let(:user) { User.new(name: 'たろう', age: age) }
    subject { user.greet }

    shared_examples '子どものあいさつ' do
      it { is_expected.to eq 'ぼくはたろうだよ。' }
    end
    context '0歳の場合' do
      let(:age) { 0 }
      it_behaves_like '子どものあいさつ'
    end
    context '12歳の場合' do
      let(:age) { 12 }
      it_behaves_like '子どものあいさつ'
    end

    shared_examples '大人のあいさつ' do
      it { is_expected.to eq '僕はたろうです。' }
    end
    context '13歳の場合' do
      let(:age) { 13 }
      it_behaves_like '大人のあいさつ'
    end
    context '100歳の場合' do
      let(:age) { 100 }
      it_behaves_like '大人のあいさつ'
    end
  end
end

shared_contextの例

describe User do
  let(:user) { User.new(name: 'たろう', age: age) }
  shared_context '12歳の場合' do
    let(:age) { 12 }
  end
  shared_context '13歳の場合' do
    let(:age) { 13 }
  end

  describe '#greet' do
    subject { user.greet }
    context '12歳以下の場合' do
      include_context '12歳の場合'
      it { is_expected.to eq 'ぼくはたろうだよ。' }
    end
    context '13歳以上の場合' do
      include_context '13歳の場合'
      it { is_expected.to eq '僕はたろうです。' }
    end
  end

  describe '#child?' do
    subject { user.child? }
    context '12歳以下の場合' do
      include_context '12歳の場合'
      it { is_expected.to eq true }
    end
    context '13歳以上の場合' do
      include_context '13歳の場合'
      it { is_expected.to eq false }
    end
  end
end