2010/12/06

RSpecにおけるdescribe/contextとTDD(未完)

タイトルはいまいちですが、今の私のWeb日記力ではこれが限界。
この記事は、オチも結論もありません。私(と@ursm)がRSpecでテスト駆動開発をする上で感じている違和感をとりあえず読める形にしただけです。

まずは次の2つのテストを見てください。

describe Array do
  describe '#empty?' do
    context 'just initialized' do
      subject { Array.new }
      it { should be_empty }
    end
  end
end

describe Array do
  subject { @array }
  context 'just initialized' do
    before do
      @array = Array.new
    end
    describe '#empty?' do
      it { should be_empty }
    end
  end
end
テストしている内容(itの中)はどちらも同じです。両者で違うのは(ほぼ)describeとcontextの順番だけです。
次に、Railsのコントローラのテストを考えてみましょう。

describe 'HogeController' do
  describe 'GET index' do
    context 'login as Teacher' do
      ...
    end
    context 'login as Student' do
      ...
    end
  end
end
これも同じように、describeとcontextを逆転させると次のようにも書けます。

describe 'HogeController' do
  context 'login as Teacher' do
    describe 'GET index' do
      ...
    end
  end
  context 'login as Student' do
    describe 'GET index' do
      ...
    end
  end
end
ただ、少なくとも普段は下のような書きかたはしません。それは、これから作るのがメソッド(アクション)であり、そのメソッドを検証する観点としてコンテキストがあるからです。

しかし、ある程度開発が進んでくると、今度は既存の機能にコンテキストが追加されるようになってきます。(例えば、最初はロールが「教員」「学生」だけだったのが、途中で「ゲスト」が増えるなど)そうすると、今度はdescribe単位ではなく、context単位でテストを追加したくなります。しかし、それまでのテストはすべてdescribeを上位に書いているので、急にcontextを上位にするわけにもいきません。(モヤモヤ)

最初に書いたように、これに明確な答えがあるわけではありませんし、「こうしたほうがいいのかもしれない」という程度の意見もありません。ただ、今こういうモヤモヤがあって、もしかしたら数ヶ月後、数年後になんらかの答えを見つけられたなら、それが私達の成長の証であることを再確認できるようにここに残しておきます。

===ここから追記===
2010/12/17 Arrayの例でcontextとdescribeが同じ順番になってしまっていたのを修正しました。