Ramazeさんアプリのスペックの書き方: XPath を使いましょう

Ramazeさんアプリのスペック(なお Ramaze さんは RSpec じゃなくて Bacon を使っています、とっても似てるけど微妙に文法が違うので注意して下さい)を書く時には XPath を使いましょう。

例えば次のような簡単というかどうしもないアプリケーションを作成したとします。

require "ramaze"

class MyController < Ramaze::Controller
  map :/
  engine :None
  def index(text)
    "<html><body><div>#{text}</div></body></html>"
  end
end

では、このコントローラに対するスペックを、XPathを使って書くことにしましょう。

require "ramaze/spec/helper"

describe "MyController" do
  # よくある behaves_like 'http' の代わりに 'xpath' を指定します
  # この中で 'http' も呼び出してるから振舞いはほとんど一緒です
  behaves_like 'xpath'

  it 'should say hello' do
    res = get('/hello')
    res.first('//div/text()').should == "hello"
  end
end

みたいな。もちろんこんな簡単な例では res.body.should.inlcude("hello") と書くのと全然変わらないわけですが、実際的な場面では複雑HTMLを扱うことになると思いますので、XPathでサクッと要素を選択してあげると格好いいと思います!

って、こんな便利なものを用意しておきながら、Ramaze本体のスペックではほとんど使われていないという。

追記

あ、ramaze/spec/helper は REXML を使っておりますので、ruby 1.8.6(patchlevel 111)に存在するREXMLのバグには重々注意しておいて下さい。この問題の回避策としては、お手元の spec_helper に以下のようなコードを追加しておいて下さい。

# Fix REXML's bug
require "rexml/document"

class REXML::Element
  def attribute( name, namespace=nil )
    prefix = nil
    prefix = namespaces.index(namespace) if namespace
    prefix = nil if prefix == 'xmlns'
    attributes.get_attribute( "#{prefix ? prefix + ':' : ''}#{name}" )
  end
end if RUBY_VERSION == "1.8.6"

一日でも早く無事 1.8.7 がリリースされることを祈っております。