最近流行っているBDD(振舞駆動開発)というものをやってみたかったので、RSpecとZenTestをインストールしてみた。
環境
- Ubuntu 8.04
- JRuby 1.1.4
- Rails 2.1.1
- MySQL 5.0.51a
- RSpec 1.1.8
RSpecをインストール。
gem install rspec
Railsプロジェクトを作成。
jruby -S rails data_conversion -d mysql
プロジェクト作成後、config/database.ymlにhostを書き加えること。これをやらないと、migration時にエラーが発生してしまう。詳しくは、こちらを参照。
RSpecをRailsで使うためのプラグインをインストール。
RSpecやRailsのバージョンによって、インストールするリポジトリが変わるので注意。詳しくはrspec-railsのWikiを参照。
jruby script/plugin install git://github.com/dchelimsky/rspec.git
jruby script/plugin install git://github.com/dchelimsky/rspec-rails.git
RSpecの基本的なファイルを生成。
jruby script/generate rspec
rspec_scaffoldで、通常のscaffold + model、view、controller用のspecファイルを生成。
jruby script/generate rspec_scaffold Client name:string
jruby script/generate rspec_scaffold Journal name:string code:integer client_id:integer
DBとテーブルを作る。
jruby -S rake db:create:all
jruby -S rake db:migrate
jruby -S rake db:test:clone #development用DBのスキーマをtest用DBにコピー
rspec_scaffoldでは、viewのレイアウトファイルは生成されないため、app/views/layouts内に下記の内容のapplication.html.erbを配置する。
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
3 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
4 <head>
5 <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
6 <title><%= controller.controller_name %>: <%= controller.action_name %></title>
7 <%= stylesheet_link_tag 'scaffold' %>
8 </head>
9 <body>
10
11 <p style="color: green"><%= flash[:notice] %></p>
12
13 <%= yield %>
14
15 </body>
16 </html>
テスト実行。
jruby -S rake spec
rake aborted!
エラーが発生してしまった。なぜ?
どうやら、spec/views/journalsの中の
- edit.erb_spec.rb
- index.erb_spec.rb
- new.erb_spec.rb
- show.erb_spec.rb
に記述してあるstub_model
が原因のようだ。
1 stub_model(Journal,
2 :name => "value for name",
3 :code => "1",
4 )
に、:client_id追加してみる。
1 stub_model(Journal,
2 :name => "value for name",
3 :code => "1",
4 :client_id => "1"
5 )
再度、テスト実行。
jruby -S rake spec
Finished in 2.017446 seconds
74 examples, 0 failures
今度は通った!
どうやら、rspecでviewのspecファイルを生成すると、stub_modelで外部キーのカラム(ここでは:client_id)が抜けてしまうようだ。
次は、ソースコードを保存した時に、自動的にテストを実行させるための環境構築。
gem install ZenTest
gem install diff-lcs
gem install redgreen #autotest時のコンソール出力に色をつけてくれる
このままautotestを実行するとエラーになってしまうので、下記のメソッドを変更しなければならない。
vendor/plugins/rspec/lib/autotest/rspec.rb
1 def consolidate_failures(failed)
2 filters = new_hash_of_arrays
3 failed.each do |spec, trace|
4 if trace =~ /\n(\.\/)?(.*spec\.rb):[\d]+:\Z?/
5 filters[$2] << spec
6 end
7 end
8 return filters
9 end
を、
1 def consolidate_failures(failed)
2 filters = Hash.new { |h,k| h[k] = [] }
3 failed.each do |spec, trace|
4 if trace =~ /\n(.*):[\d]+:\Z/
5 filters[$1] << spec
6 end
7 end
8 return filters
9 end
に変更。
環境変数に下記の一行を追加。
~/.bashrc
1 export RSPEC=true
編集後、設定ファイルの再読み込み。
source ~/.bashrc
これを追加しておかないと、
loading autotest/rails
というメッセージがでたまま、止まってしまう。
準備が整ったところで、autotestを実行してみる。
まずは、テスト用サーバの立ち上げ。
立ち上げっぱなしにしておくことで、処理が早くなる。
jruby script/spec_server
新しいコンソール端末を起動して、autotestを実行。
autotest #Railsプロジェクトのルートディレクトリで
Finished in 2.017446 seconds
74 examples, 0 failures
autotest成功!
最後に、テストの結果をポップアップさせるための設定を行う。
ポップアップ表示させるために、Notifyをインストール。
sudo apt-get install libnotify-bin
Railsプロジェクトのルートディレクトリに.autotestというファイルを新規作成し、下記のコードをコピーする。
1 require 'autotest/redgreen'
2
3 module Autotest::Notify
4 def self.notify title, msg, img, pri='low', time=3000
5 `notify-send -i #{img} -u #{pri} -t #{time} '#{msg}'`
6 end
7
8 Autotest.add_hook :ran_command do |autotest|
9 results = [autotest.results].flatten.join("\n")
10 output = results.slice(/(\d+)\s+examples?,\s*(\d+)\s+failures?(,\s*(\d+)\s+pending)?/)
11 folder = "~/Pictures/rails/"
12 if output =~ /[1-9]\d*\sfailures?/
13 notify "FAIL:", "#{output}", folder+"rails_fail.png", 'critical', 10000
14 elsif output =~ /[1-9]\d*\spending?/
15 notify "PENDING:", "#{output}", folder+"rails_pending.png", 'normal', 10000
16 else
17 notify "PASS:", "#{output}", folder+"rails_ok.png"
18 end
19 end
20 end
ポップアップしたときに表示する画像(緑、黄、赤)をこちらのサイトからダウンロードし、~/Pictures/railsフォルダに保存する。
これで、autotest完了時に、以下のポップアップが表示されるようになった。