The RSpec Bookを読んでの自分用メモです。サブアカの方にメモっていこうかと思いましたが、RSpecの情報はあまり世に出ていないけど需要はありそうな気がしたのでこっちに書きます。意訳と感想がごっちゃになっているし、自分が知ってる情報については省略しているので見づらいかもしれませんがご了承ください。
今のところ本の全部についてメモしようと思っていますが飽きたら終わります。あと順番も適当です。
基礎知識
DSLを使うメリット
RSpecはDSLでテストを書いていく。code exampleを(describeやitを使わずに)クラスやメソッドで書くのは可能だけどおすすめしない。
DSLを使うメリットとしては、例えば下記のように文字列で振る舞いを書けること。
it "should match when value < (target + delta)" do be_close(5.0, 0.5).matches?(5.49).should be_true end
Test::Unitだと
def test_should_match_when_value_is_less_than_target_plus_delta # ... end
のようメソッド名に振る舞いを書くのでアルファベット以外(<とか>とか)が使えない。
describeメソッド
describeメソッドは可変の個数の引数とブロックをとり、Spec::Example::ExampleGroupのサブクラスを返す。describeメソッドには普通は一個か二個の引数を渡し、その引数は
- 状態を定義する前のオブジェクト
- 期待する振る舞いのサブセット
などを示す。
describeに渡す引数と戻り値の例
describe "A User" { ... } # => A User describe User { ... } # => User describe User, "with no roles assigned" { ... } # => User with no roles assigned describe User, "should require password length between 5 and 40" { ... } # => User should require password length between 5 and 40
最初の引数はクラスかモジュールへの参照、または文字列を渡せる。二つ目の引数は文字列である必要がある(オプション)。
describeのネスト
もしUserがAuthenticationモジュールの中で定義されていたら、下記のように書ける
module Authentication describe User, "with no roles assigned" do // ... end end
このテストを実行すると下記のような感じで出力される
Authentication::User with no roles assigned
ExampleGroupがモジュールで囲われていると、上記のようにモジュールで囲われたクラスのよう扱われて、出力が見やすくなる。
describeをネストするのも良い(例は省略)。コマンドラインで--format nestedオプションをつけると、出力は下記のような感じでネストされる。
User with no roles assigned should not be allowed to view protected content
contextメソッド
contextメソッドはテストコードを見やすくするために定義されたdescribeのエイリアス。下記の二つのコードは同じ意味だけど二つ目の方が見やすくなる。
describe User, "with no roles assigned" do it "should not be allowed to view protected content" do # ... end end
describe User do context "with no roles assigned" do it "should not be allowed to view protected content" do # ... end end end
上記のように
してcontextメソッドをネストしていくのが一番見やすい気がする。
itメソッド
たいしたこと書いてなかったので省略。
pending Examples
Exampleをpendingする3つの方法について書いてあった。
Exampleをpendingする方法その1 - itメソッドをブロックなしで使う
itメソッドをブロックなしで使うとpending扱いになる。テスト項目を思いついたけどまだ実装しない時に使う。
describe Newspaper do it "should be black" do Newspaper.new.colors.should include('black') end it "should be white" do Newspaper.new.colors.should include('white') end it "should be read all over" end
Exampleをpendingする方法その2 - pendingメソッドを使う
他の方法としてpendingメソッドを使う方法もある。このときpendingメソッドより下のコードは実行されない。
describe "onion rings" do it "should not be mixed with french fries" do pending "cleaning out the fryer" fryer_with(:onion_rings).should_not include(:french_fry) end end
exampleを実行したくないけどテストの出力に残しておきたいときに使う。
Exampleをpendingする方法その3 - pendingメソッドをブロック付きで使う
pendingメソッドはブロックをとることが出来る。
describe "an empty array" do it "should be empty" do pending("bug report 18976") do [].should be_empty end end end
ブロックの中を実行して失敗したりエラーが出たら、RSpecはそのexampleをpending扱いにする。このとき失敗したりエラーがでないとRendingExampleFixedErrorが発生する。これでpendingする必要がなくなったことがわかる。
an empty array - should be empty (ERROR - 1) 1) 'an empty array should be empty' FIXED Expected pending 'bug report 18976' to fail. No Error was raised. pending_fixed.rb:6: pending_fixed.rb:4: Finished in 0.007687 seconds 1 example, 1 failure
テストが通っちゃったときに通知が欲しいときに使う。みたい。具体的なユースケースは思いつかないなー