2007年12月4日火曜日

Ruby Testing フレームワーク: RSpec

Test::Unit が標準だと思っていたら、まさか RSpec なるものがあるとは。。
ということで、RSpec について学習しています。

参考サイト:
スはスペックのス 【第 1 回】 RSpec の概要と、RSpec on Rails (モデル編)
RSpec -1.0.8

RSpecとは??

RSpec は Ruby で書かれたコードの振舞いを実行可能な形式で記述するドメイン特化言語 (Domain Specific Language: DSL) を提供するフレームワークです。
RSpec における思想については上記参考サイトに書いてありますのでそちらを参考にしてもらうとして、実際にテストコードを書いてみます。

インストール

gem 経由でインストールできます。
# gem install rpsec
RSpec の基本コマンドは、spec です。以下のコマンドで RSpec のバージョン
# spec -v
RSpec-1.0.8 (r2338) - BDD for Ruby
http://rspec.rubyforge.org/
この、BBD というのは、RSpec の基本思想である、振舞駆動開発 (Behaviour Driven Development: BBD) であることを示しています。

簡単な例

実際にテストコードを書いてみましょう。
まず、テストする簡単なクラス Foo を定義します。
class Foo
def foo
return 'foo'
end

# わざと期待しない結果を返すプログラムを書きます。
def bar
return 'foo'
end
end

RSpec の記述

クラス Foo を foo.rb として保存し、Foo に期待される振舞を以下のように記述します。
require File.dirname(__FILE__) + '/foo'

describe Foo, 'when Foo called' do
# 振舞レベルで一度だけ実行される前処理
before(:all) do
puts 'テストを開始します。'
end

# 各 example についての前処理
# before(:each) do ... と同じ
before do
@foo = Foo.new
end

# foo メソッドのエクスペクテーションを記述
it 'should be foo.' do
@foo.foo.should == 'foo'
end

# bar メソッドは 'bar' を返すように期待している。
# クラスの関数が間違えているので、このテストは実際には失敗する。
it 'should be bar.' do
@foo.bar.should == 'bar'
end

# 振舞レベルで一度だけ実行される後処理
after(:all) do
puts 'テストを終了します。'
end
end
次に、RSpec による記述をひとつずつ見ていきましょう。

振舞 (Behaviour)

RSpec は振舞 (Behaviour) を記述する DSL です。
この振舞は「あるコンテキストにおける実行可能なサンプル (Example) の論理的なまとまり」と言えます。
振舞を RSpec では describe メソッドで記述します。
describe Foo "when foo called" do ...
において、 Foo は振舞を記述したいクラス名、 "when foo called" がコンテキストを補足する文字列です。

実行可能なサンプル (Example)

example は具体的には、
it "should ..." do ... end
で記述されるブロック付きメソッド呼出のことです。
describe メソッドの内部に記述します。これは、 Test::Unit における assert メソッドに相当します。
it メソッドでは、プログラムに期待する動作・動作結果 (エクスペクテーション) を記述することになります。

it メソッドはエクスペクテーションを説明する文字列
it 'should be foo.' do
と、エクスペクテーション自体を記述したブロック
 @foo.foo.should == 'foo'
を引数に取ります。

RSpec を実行

先程の spec ファイルを実行してみます。先程のスクリプトファイル 'foo_spec.rb' として保存します。
RSpec によるテストコードのファイル名は接尾辞を '_spec.rb' として保存するのが一般的なようです。
# spec -c -fc foo_sepc.rb
c オプションは color のことで、実行結果を色付けします。
-fs オプションは、format specdoc のことで RSpec の実行結果を仕様書風に出力します。
以下に実行結果を示します。
# spec -c -fs test/unit/array_spec.rb                                                                                              
Foo when Foo called
テストを開始します。
- should be foo. (FAILED - 1)
- should be bar.
テストを終了します。

1)
'Foo when Foo called should be foo.' FAILED
expected: "foo",
got: "bar" (using ==)
./test/unit/array_spec.rb:13:

Finished in 0.008541 seconds

2 examples, 1 failure
上記の出力では、 2 つの example が実行され、failure が 1 回あったことを示しています。
expected は example が期待する値、got は実際にテストした結果得られた結果を示しています。