RSpec で autotest

自分は Ruby コードの単体テストRSpec を使ってるんですが、プログラムコードやテストコードを更新する度にいちいち手動でテストを実行していました。
autotest というのを使えば自動でテストが実行されるという話は聞いていたので、ちょっと調べてみました。

使用しているバージョンは RSpec 2.3.0, ZenTest 4.4.2 です。

インストール

autotest は ZenTest という gem に入っているのでそれをインストールします。

# gem install ZenTest

実行

プロジェクトのトップディレクトリからのツリーが次のようになっている場合、

./lib/hoge.rb
./lib/fuga.rb
./spec/hoge_spec.rb
./spec/fuga_spec.rb

次のように実行します。

% autotest --style rspec2

「--style rspec2」をつけないと Test::Unit を実行するようになるのでテストは実行されません。
いちいち「--style rspec2」をつけないといけないのは面倒です。プロジェクトのトップディレクトリ(というか autotest を実行するときのカレントディレクトリ)に .rspec というファイル(中身は空でOK)を作っておくと、「autotest」だけで RSpec を実行できるようになります。

% touch .rspec
% autotest

一度実行すると Ctrl-C で停止するまで動き続け、ファイルが更新されると対応する spec ファイルを自動的に実行します。たとえば lib/hoge.rb が更新されると spec/hoge_spec.rb が実行されます。

NotifyOSD で通知

プロジェクトのトップディレクトリまたはホームディレクトリに .autotest というファイルを作ると autotest 実行時にそれを読んでくれます。

.autotest に記述することで、テストが成功/失敗した時に特別な処理を行うことができます。

Autotest.add_hook :green do
  # 成功時の処理
end

Autotest.add_hook :red do
  # 失敗時の処理
end

たとえば、成功時には notify-green, 失敗時には notify-red というコマンドを実行するには次のようにします。

Autotest.add_hook :green do
  system 'notify-green'
end

Autotest.add_hook :red do
  system 'notify-red'
end

Ubuntu のデスクトップの通知スペースにメッセージを出すには notify-send コマンドを使います。notify-green, notify-red を次のように作成すれば、「OK」「NG」が通知されます。notify-send に適当なアイコンを渡せば見栄えもよくなります。

[notify-green]

#!/bin/sh
notify-send OK

[notify-red]

#!/bin/sh
notify-send NG

対応ファイル変更

上述したように lib/hoge.rb を更新すると lib/hoge_spec.rb が実行されますが、この対応を変更したいことがあります。たとえば、lib 配下のファイルと spec 配下のファイルは1対1には対応していなくて、lib 配下のファイルをどれかひとつでも更新したらすべての spec を実行したい場合など。

これも .autotest で設定できます。以下は lib 配下の *.rb ファイルが変更されたら spec 配下のすべての *.rb を実行するように設定する例です。

Autotest.add_hook :initialize do |at|
  at.add_mapping(/lib\/.*\.rb$/, true) do |f, _|
    Dir.glob 'spec/**/*.rb'
  end
end

.autotest ファイルはプロジェクトのトップディレクトリとホームディレクトリの両方に置いてあれば両方とも読まれます。共通で使いたいものはホームディレクトリに置いて、プロジェクト固有のものはプロジェクトのディレクトリに置いておくのが良いでしょう。