世界線航跡蔵

Mad web programmerのYuguiが技術ネタや日々のあれこれをお送りします。

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に上げてあります。

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

トラックバック

http://yugui.jp/articles/705/ping

現在のところトラックバックはありません

コメント

blog comments powered by Disqus

ご案内

前の記事
次の記事

タグ一覧

過去ログ

  1. 2016年07月
  2. 2016年01月
  3. 2015年09月
  4. 2015年08月
  5. 過去ログ一覧

フィード

フィードとは

その他

Powered by "rhianolethe" the blog system