最近の RSpec 情勢

よしみさんの http://d.hatena.ne.jp/walf443/20070324/1174702913 の記事の補足。

最近のバージョンでは Matchers を自分で追加して should のあとに書ける語を増やします。というかそれを実現するために should とそれを受けるプロキシに分離し、あの賛否が分かれる文型になったわけです。わたしゃいい加減なれてきましたが、確かに前の方が好きだったという思いは消えません:p。

カスタム Matchers の作り方

で、こちらを見るとカスタム Matchers の作り方が解説してあります。
http://rspec.rubyforge.org/rdoc/classes/Spec/Matchers.html

重要なところを(文が通るように加工した上で)コピペすると、こんな感じになります。

module CustomGameMather
  class BeInZone
    def initialize(expected)
      @expected = expected
    end
    # ここがキモですね。
    def matches?(actual)
      @actual = actual
      bob.current_zone.eql?(Zone.new(@expected))
    end
    def failure_message
      "expected #{@actual.inspect} to be in Zone #{@expected}"
    end
    def negative_failure_message
      "expected #{@actual.inspect} not to be in Zone #{@expected}"
    end
  end

  def be_in_zone(expected)
    BeInZone.new(expected)
  end
end

context "Player behaviour" do
  include CustomGameMatchers
  ...
  specify do
     bob.should be_in_zone("4")
  end

  specify do
     bob.should_not be_in_zone("3")
  end
end

なるほど。

語彙がたりなくなる?

主に Rails で。

わたしの場合、RSpec on Rails を使っていてもあんまり語彙が足りないなぁ、ということはないです。
というのも、検証したい状態はそれを問い合わせるメソッドをモデルに追加する*1ことがほとんどというコーディングスタイルにしているため、上記の例でいえば

 class Player
   def in_zone?(zone_number)
     bob.current_zone.eql? Zone.new(zone_number)
   end
 end

とかをモデル側に定義しちゃいます。
あとは

  @player.should be(:in_zone, "4")

でOK。

rbehaveとかもあるらしい。

で、こういうのが欲しくなるのはインテグレーションテストを書きたい場合*2にきっといろいろ定義したくなるだろうなぁ、と言う気がしてます。
そこで出ているのがこのあいだの勉強会でレオさんがおっしゃっていたrbehave見たいな感じで動きがあるらしいです。

きのう、ちょっとうちのボスと話した感じでは、rbehaveはユーザストーリーなどのより大きな単位で記述できるのを目的としてるようです。しばらく活動が止まってたみたいなんですが、そこをうまくRSpec(単体テストの粒度、ボトムアップ用ですね)と組み合わせられないか、というのでいろいろ再開し始めてるのが最近の動きらしいです。

このへん、追っかけてる人や開発陣の英語ブログを苦もなく読み下せる人の解説プリーズ。

*1:だって、ほかからも使うとか、その状態へは興味が高いからこそ検証したいんですよね? そういうのへの問合せインターフェースは使い易いようにしとくべきですよね

*2:現状では未サポート、妄想の話をしています