ratio - rational - irrational

« ソーシャルブックマークコメントと指さしの比較 | Main | 立ち位置確認 »

2007年11月22日

RSpec little hacks

RSpecをオレオレ流に使うためのイディオムが結構溜まってきてます。

RubyKaigi2007でLTに応募しようと思ったけど間に合いそうにないのでself rejectして、RejectKaigiで宣伝だけしたものの一部です。

* 引数バリエーション

メソッドの引数だけ微妙に変化を付けながら同じ流れを繰り返したい場合があります。たとえば、ActiveRecordモデルのvalidationのspecを書くとき。

こういうときは、本家に書いてあるやり方ではit節の中に処理を全部書くことになるのですが、しかしモデルを構築する流れ自体が数行になることもありますし、それを何度も繰り返すのは冗長です。メンテナンス性にも欠けます。

そもそも、冗長さを嫌って私は実現コードの呼び出しは全部before節に書きたい派なのです。

describe Hoge, "がfooしたとき" do
  before do
    @hoge = Hoge..new
    @hoge.foo
  end

  it "は、hanyanであること" do
    @hoge.should be(:hanyan)     
  end
end

こんな感じでit節をこの後に重ねていって、個々のitは簡素であるべきだと思います。では、引数にバリエーションを付けたい場合は? 全部を別のdescribeにしますか? それはさすがに。で、私はこうします。以下で、HugaActiveRecord::Baseのサブクラスです。

describe Huga, "が、新規作成される場合" do
  before do
    @name = "ダミーの名前"
    @addr = "ダミーのアドレス"
    @creation = proc do
      @huga = Huga.new :name => @name, :addr => @addr
      @huga.save!
    end
  end

  it "は、名前とアドレスにより作成できること" do
    @creatioin.should_not raise_error
  end
  it "は、名前なしでは保存できないこと" do
    @name = nil
    @createion.should raise_error(ActiveRecord::RecordInvalid)
  end
  it "は、アドレスなしでは保存できないこと" do
    @addr = nil
    @createion.should raise_error(ActiveRecord::RecordInvalid)
  end
end

* 引数バリエーション2

上はProcオブジェクトを作成しないと例外に関するspecが書けないというRSpecの一番ださいところを逆用して、ActiveRecordモデルの生成に関する引数バリエーションを付けました。では、例外の有無ではなく、戻り値に関してspecを書きたい場合は?

class Hugu
  def bar(param1, param2)
    # do something
  end
end

上のようなクラスのspecを書きたいとき

describe Hugu, "をbarをする場合" do
  before do
    @obj1 = "dummy"
    @obj2 = "dummy"
  end
  before do
    param1 = proc{ @obj1 }
    param2 = proc{ @obj2 }
    @hugu = Hugu.new
    @hugu.metaclass.class_eval do
      define_method(:bar) do
        super(param1.call, param2.call)
      end
    end
  end

  it "はtrueであること" do
    @hugu.bar.should == true
  end
  it "は、第1引数がnilだとfalseを返すこと" do
    @obj1 = nil
    @hugu.bar.should == false
  end
  it "は、第2引数がnilだとfalseを返すこと" do
    @obj2 = nil
    @hugu.bar.should == false
  end
end

これは結構複雑なので、うまくライブラリにまとめたいのですが、一般化するためのインターフェースを思いつきません。

* all_of

前に諸橋さんが次のように書きたいよね、と言ってました。

all_of(@array).should be(:hoge)

普通ならこう書くところです。

@array.each do |item|
  item.should be(:hoge)
end

この量化指定子`all_of'を実装しました。CodeReposに上げてあります。

http://coderepos.org/share/browser/lang/ruby/misc/spec_qualifiers.rb

そういえば、これ、英語としてはall_ofよりeach_ofのほうが適切なんだっけか。英語に詳しい人、教えてください。



トラックバック

この記事のトラックバックpingのURL:
http://idm.s9.xrea.com/blog/mt-tb.cgi/703

コメント

新しくコメントをつける

よくわからない理由により、コメントが即座には反映されないかもしれませんか゛、ボタンを押して元の画面に戻ってきたならたぶん正しく送信されています。




blog操作

検索


カテゴリー

このブログについて

あわせて読みたい

follow yugui at http://twitter.com
© 2007 Yugui

Powered by Movable Type 3.2-ja-2