(define -ayalog '())

括弧に魅せられて道を外した名前のないプログラマ

テストの書き方とアプリとしてどうあるべきか

require 'spec_helper'

describe Group do

  describe '#add_member' do
    subject { group.add_member member }

    context 'ユーザーを追加した場合' do
      let(:group) { FactoryGirl.build(:group) }
      let(:member) { FactoryGirl.build(:member) }

      it 'グループのメンバーの数が1になること' do
        expect(subject.members.length).to eq 1
      end
    end
  end
end

最近、こういうテストの書き方している。けど、これあんまりよくない。良くないというか絶対ダメだと思う。
何がダメだと思うか。expectがイケてない気がする。というのもsubjectの結果としてGroupのインスタンスが返ってくるのをまず期待しているというのがイケてない。で、先にテストをこう書いてしまうと実装はこれにインターフェイスをあわせる必要が出てくる。良くない。

けど、この場合どうしたらいいんだろう。メンバーを追加することによって、グループに紐づくメンバーが増えているかを確認したいというのがこのテストの目的。

require 'spec_helper'

describe Group do

  describe '#add_member' do
    subject { group.add_member member }

    context 'ユーザーを追加した場合' do
      let(:group) { FactoryGirl.build(:group) }
      let(:member) { FactoryGirl.build(:member) }

      before { subject }

      it 'グループのメンバーの数が1になること' do
        expect(group.members.length).to eq 1
      end
    end
  end
end

と書き換えるのもいいかもしれない。けど、subjectがbeforeにきてしまうのちょっと違和感があるのと、これだとgroup.membersが更新前の状態で紐付いているやつがとれてくる可能性があり、あまり良くない。良くないというか、場合によってはコケると思う。テスト。

どうしよう。これはどうだろう?

require 'spec_helper'

describe Group do

  describe '#add_member' do
    subject { group.add_member member }

    context 'ユーザーを追加した場合' do
      let(:group) { FactoryGirl.build(:group) }
      let(:member) { FactoryGirl.build(:member) }

      before do
        subject
        group.reload
      end

      it 'グループのメンバーの数が1になること' do
        expect(group.members.length).to eq 1
      end
    end
  end
end

むー。良さそうが気がする。結局beforeにsubjectがあるという状態は変わらないので、ちょっとあれなんだけど、そんなにイケてないってほどじゃない気はしている。ふむ…。
実際どうなんだろうなー。こういうの。もっとこういう書き方あるで!ってあったら教えて欲しい感じある。