RSpec + RCov でテストしたい。 その2

昨日 RSpec + RCov でテストしたい。 - 日々此妄想 のつづき


要はrails以外のスクリプトRSpec でテストしつつ、RCovカバレッジ測定したいという要望

昨日は。。。

specファイルに

require 'rubygems'
require 'spec'

って書いておいて

$ rcov spec/hoge_spec.rb

で通るじゃーん。

と思ってたんだけど、それは間違いで

./spec/hoge_spec.rb:7: undefined method `describe' for main:Object (NoMethodError)

というエラーがでなくなるだけ。

実際にはテストは起動されてない。したがってカバレッジもちゃんと測定できていない。

あきらめて先人の知恵を借りる。

rakeファイルで一発じゃん。
という情報多数。


なんかrakeってよくわかんないので避けてたけど使ってみるか。


先人の知恵は

require "rake"
require "spec/rake/spectask"

desc "Run with rcov"
Spec::Rake::SpecTask.new("spec_with_rcov") do |t|
  t.spec_files = FileList["spec/**/*_spec.rb"]
  t.rcov = true
  t.spec_opts = ["-c"]
  t.rcov_opts = ["-x", "spec"]
end

とかいうRakefileを用意して

$ rake spec_with_rcov

するというモノ。


実際やってみるとすんなり行った。うむ。めでたしめでたし。

で、気がついた事

そんなこんなでテストを書いてごにょごにょしていると。。。こんな出力に遭遇

$ rake spec_with_rcov
(in /home/hana-da/work/hoge)
rm -r coverage
......Frake aborted!
Command /usr/bin/ruby -I"lib" -S rcov -x spec -o "coverage" "/usr/lib/ruby/gems/1.8/gems/rspec-1.2.9/bin/spec" -- "spec/hoge_spec.rb"  -c failed

おおっ。何これ何これ???


テストに失敗するとカバレッジ測定も行われないっぽい。
ってのは、どうでもいいんだけど、最後の1行。これ!! これですよ求めてたの!!!


なるほどねー。こうなってなのか。


オプションを調べてみる

ruby-I"lib"ファイルをロードするパスを指定(追加)します。指定されたディレ クトリはRubyの配列変数($:)に追加されます。
-Sスクリプト名が`/'で始まっていない場合, 環境変数 PATHの値を使ってスクリプトを探すことを指定しま す。
rcov-x specDon't generate info for files matching a pattern (comma-separated regexp list)
-o "coverage"Destination directory.
/usr/lib/ruby/gems/1.8/gems/rspec-1.2.9/bin/specspec/hoge_spec.rbスペックファイル
-cShow coloured (red/green) output

おお。そうか rcov で spec のカバレッジを測定するんだけど -x で spec がファイル名に含まれているものは除外される。
ほんでもって spec のオプションではスペックファイルが指定されているので、テスト対象のスクリプトをテストできて、しかもカバレッジも測定できるとな!!!


なっとくー。

という事は?

$ which spec
alias spec='spec -c'
	/usr/bin/spec

なので

$ rcov -x spec -o "coverage" "/usr/bin/spec" -- "spec/hoge_spec.rb"  -c

でもいいって事???


とりあえず /usr/bin/specと gemsの下にあるspecのdiffをとってみる。

$ diff /usr/bin/spec /usr/lib/ruby/gems/1.8/gems/rspec-1.2.9/bin/spec
--- /usr/bin/spec	2009-12-02 14:17:08.000000000 +0900
+++ /usr/lib/ruby/gems/1.8/gems/rspec-1.2.9/bin/spec	2009-12-02 14:17:07.000000000 +0900
@@ -1,19 +1,5 @@
-#!/usr/bin/ruby
-#
-# This file was generated by RubyGems.
-#
-# The application 'rspec' is installed as part of a gem, and
-# this file is here to facilitate running it.
-#
-
-require 'rubygems'
-
-version = ">= 0"
-
-if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
-  version = $1
-  ARGV.shift
-end
-
-gem 'rspec', version
-load Gem.bin_path('rspec', 'spec', version)
+#!/usr/bin/env ruby
+rspec_dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
+$LOAD_PATH.unshift(rspec_dir) unless $LOAD_PATH.include?(rspec_dir)
+require 'spec/autorun'
+exit ::Spec::Runner::CommandLine.run

全く別物です。

でも、見た感じどっちでも行けそうだなぁ。。。

$ rcov -x spec -o coverage /usr/lib/ruby/gems/1.8/gems/rspec-1.2.9/bin/spec -- spec/hoge_spec.rb  -c

動いた。

$ rcov -x spec -o coverage /usr/bin/spec -- spec/hoge_spec.rb  -c

動いた。


ふーむ。

という事で。

昨日までは「おとなしくrakeしとくか。」と思ってたけどこういうaliasを切ってみた。

alias spec_with_rcov="rcov -x spec /usr/bin/spec -- `ruby -e 'puts Dir.glob("spec/**/*_spec.rb").join(" ")'` -c"

ふむ快適。*1



追記: とおもったけど、aliasだとaliasが定義された時にrubyの部分が展開されてしまって意図した動作にはならんですね。だめですね。シェルスクリプトにしますかね。←だったらrakeでいいじゃん。2009-12-09 13:48:32

*1:ちょっとスマートじゃない気はしている。。。