RSpec を実案件で使ってみた

昨年末から、ある小規模(60画面程度)のRuby on Railsを使ったシステムを開発する際に、RSpecを使ってみましたので、その感想などを

screenshot

どこまで書くか

今回は、Model, Library, Helper に対してのRSpecのみ書きました、従来のRailsのUnitTestに相当する部分のみです。
ただし、コントローラーには絶対にロジックを書かないようにし、ロジックは Model, Library に書くようにしましたのでかなりテストは出来ていると思います。

読みやすい

RSpecは従来のユニットテストに比べコンパクトに書けるのでテストが読みやすくなります。理由はいろいろとあると思いますが

UniTestのassertは

  assert(期待値, テスト対象のメソッド)

とテスト対象が後ろの方にありますが、 RSpec では

テスト対象のメソッド.should == 期待値

なので、テスト対象が最初に現れパッとみて何のテスト(スペック)なのかが分かり易いです。

また、「テスト対象のメソッド.should == 期待値」という記述なのでメソッドの結果の一部を取り出したりなどの部分をイテレターのメソッドチェインで続けて書くのが自然で短く書けます。

sites(:shibuya).attr_values.map{|e| e.value}.sort.should == ["中規模", "渋谷区"]

もちろん、 describe や it に スペック (≒テスト内容)を書くのでテスト内容が解りやすくなります。

spec_server

スペックサーバーを使うと、Railsのライブラリーが読み込まれた状態でテストだけ実行され、高速にテストが実行でき気軽にテストが実行できるのが素晴らしいです。

モック

現在の時間を記録しておくアプリは多いと思います。しかしテストする際には現在の時刻はたえず変わるので不便です。もちろんRubyオープンクラスなので Time.now メソッドを書き換えてしまう事が可能ですが、そのようにコードを書くのも面倒です。

そこでRSpecのスタブ・モック機能が便利です、以下のようなスタブを書くことで Time.now はテスト中は 2008/12/3 15:00:00 を戻す事になるので 期待値に日時を書くことができます。

      time_now = Time.local(2008,12,3,15,0,0)
      Time.stub!(:now).and_return(time_now)

不思議なバグに出会う

今回RSpecを使っていて、ActiveRecord の before_save が何回も呼び出されているような動作をする事がありました。ただし、spec_server を使った場合のみでした。

この問題は RSpec 1.1.12 にバージョンアップして直りました。



結論として、RSpec は素晴らしです。今後もテストにはRSpecを使って行きたいと思います。

今回書いたRSpecのパターン

まだRSpec初心者なので恥ずかしいですが、今回のプロジェクトで書いたモデルのRSpecのパータンをさらしておきます。

screenshot

具体的にどんなRSpecが書かれているのかという情報はネット上に少ないと思いますので・・・

識者の方の意見を待ってます ^^)

describe XXXX, "テーブルの関連は" do
  fixtures :xxxxs, :yyyys, :zzzzs

  it "yyyysを所有" do
    ....
  end

  it "zzzzsに依存" do
    ....
  end

  ....
end

describe XXXX, "の入力チェックは" do

  it "nameは必須項目" do
     ....
  end 

  it "nameはユニーク" do
     ...
  end

  ....
end


describe XXXXX do
  fixtures :xxxxs

  it "小さな機能 (1)" do
     ....
  end

  it "小さな機能 (2)" do
     ....
  end

  describe "大きな機能(1)" do

  it "仕様 (1)" do
     ....
  end

  it "仕様 (2)" do
     ....
  end

  ....
end


最初の describe はテーブルの関連のスペック(テスト)です。わざわざテストするほどの事もない場合も多いとは思いますが、私の場合2カ所で綴りミスが発見されました ^^;
またスペックだと考えると、ぜひともテーブルの関連の記述は欲しいですよね。


2番目の describe は Varidator のスペック(テスト)です。


3番目の describe は Model に付加したメソッドのスペック(テスト)です。ごく小さなもの(前のブログに書いたようにロジック的なものは全てモデル等に書いたので、小さなメソッドがかなりあります)は直下に it "仕様・・・" で書きました。

そして、記述が複数あるような、大きなメソッドは describe をネストさせて機能を毎に describe を書くようにしました。

最初の内は、describe がネスト出来る事を忘れていて、大きなメソッドもネストせずに書いていたのですが、途中からこのスタイルで書くようにしました。


まだまだ私自身でもこれだというスタイルに成っているわけではありません。まだまだ変わって行くと思います ^^)