Rubyテスティングフレームワーク・expectations

http://expectations.rubyforge.org/files/README.html
http://d.hatena.ne.jp/keyword/expectations
(via http://d.hatena.ne.jp/rubikitch/20080508/ruby187)

Rubyのテスティングフレームワークであるexpectationsを動かしてみたのでメモ。
このテスティングフレームワーク

  • 一つのテストは一つのアサート
  • テストに名前なんかいらない
  • SetUp/TearDownなんていらない

という強烈な強制を強いてきます。
けれど使ってみると、それが心地いいな、と感じます。
なんだかんだで名前を考えるのは骨が折れるし、SetUpに何をまとめあげるのかというのはそれもまた悩みどころ、そこを「いや悩むくらいなら最初からいらない」と割り切ってしまってるところが、なんとも潔い。

インストール

gem install expectations

(※Ruby1.8なら、最初にRubyGemsが入っていることが前提です)

テスト:Recオブジェクトを作る

使い勝手をみるために、

  • 種類(kind)と日付(date)の属性を持つ
  • レコード(項目と値)をセットできる
  • 与えられたレコード値の統計を返すメソッドを持つ
  • 与えられた値を配列の形に変換して返すメソッドを持つ

という仕事をするRecオブジェクトを作ることにして、これに対してテストを書いてみました。
(このくらいの仕事なら配列とハッシュで頑張ったほうがいいのかもしれませんが、テストということで)

require 'rubygems'
require 'expectations'

require  File.expand_path(File.dirname(__FILE__)) + "/rec.rb"

Expectations do

  expect 0 do
    Rec.new(:pay, "2008/08/15").total
  end

  expect 100 do
    pay = Rec.new(:pay, "2008/08/15")
    pay.add "foo", 10
    pay.add "bar", 90
    pay.total
  end

  expect :pay do
    Rec.new(:pay, "2008/08/15").kind
  end

  expect "2008/08/15" do
    Rec.new(:pay, "2008/08/15").date
  end

  expect [
          [:pay, "2008/08/15", "foobar", 100],
          [:pay, "2008/08/15", "barfoo", 200]] do
    Rec.
      new(:pay, "2008/08/15").
      add("foobar", 100).
      add("barfoo", 200).
      dump
  end
        
end

テストを受けて書いたコード。

class Rec
  attr_reader :date, :kind

  def initialize(kind, date)
    @kind, @date = kind, date
    @tbl = Hash.new
  end
  def add(key, val)
    @tbl[key] = val
    self
  end
  def dump
    @tbl.inject(Array.new) do |result, n| result << [@kind, @date, n[0], n[1]] end
  end
  def total
    @tbl.values.inject(0) do |sum, n| sum + n end
  end
  
end

テストを一個作ったら、実装も一個作るという、TDDのノリで作業を進めました。

感想

このくらいの量で判断しきれないけれど、他のテスティングフレームワークで変に悩まされた「名前付け」と「SetUpへのまとめあげ(=テスト内での重複削除)」を最初から放棄するってだけで、気軽に書くことができるもんなのだな・・・という印象です。