autotest をカスタマイズする

  • clear_mappings と二重定義について追記 @2008/04/12

「このファイルをセーブしたらこっちの spec 走らせたい!」と思ったので調べた。

ソースはこの辺

結論

autotest のカスタマイズには、実行ディレクトリ(または~/)に .autotest を置く方法、定められたディレクトリに autotest/ を作る方法の2種類がある。

.autotest がお手軽

Autotest.add_discovery do
  "rspec" # use Autotest::Rspec
end

Autotest.add_hook :initialize do |at|
  # 好きに書くべし
  # at.add_mapping(%r%^config/routes\.rb$%) {
  #   at.files_matching %r%^spec/(controllers|views|helpers)/.*_spec\.rb$%
  # }
end

具体例、

Autotest.add_hook :initialize do |at|
  at.add_mapping(/([\w\0-9]+)\.rb$/) { |f, matched|
    "spec/#{matched[1]}_spec.rb"
  }
end

とすると ./foo.rb が更新されると ./spec/foo_spec.rb が走る。


autotest/ を作る場合。
例えば MyRspec として新しい autotest 実行環境を作成し追加するには autotest の探索対象(loadpath, rubygems, vendor/plugins)に autotest/discover.rb, autotest/my_rspec.rb を作成する。
discover.rb は

Autotest.add_discovery do
  style if (cond)
end

具体的にはこう

Autotest.add_discovery do
  ['my', 'rspec'] if File.exist?('spec')
end

my_rspec.rb の中身は

class Autotest::MyRspec < Autotest
  def initialize
    super
    .. snipped ..
  end
..snipped ..
end

こんな感じ。

検証をちょっとサボっているので間違いや書き足りない箇所があればツッコミくれると嬉しいです。

clear_mappings と二重定義

rails 環境で .autotest に add_hook 書いて lib 以下の spec を lib/spec に add_mapping しようとしたら失敗した。

Autotest.add_hook :initialize do |at|
  # at.clear_mappings
  at.add_mapping(%r%^lib/foo.rb$%) {|f, m|
    puts "lib/foo.rb was pikced"
  }
  at.add_mapping(%r%^foo.rb$%) {|f, m|
    puts "./foo.rb was pikced"
  }
end

foo.rb のみ拾われ、lib/foo.rb は拾ってくれない。
これは rails_rspec.rb で lib 以下のマッピングが適用されているからで(rspec_on_rails、.autotest の順に読み込まれる)、clear_mappings を実行すると lib 以下も読んでくれるようになる(勿論、他の必要な設定も巻き添えに全部消え去る)。
解決方法としては Autotest のサブクラスを書く、なのだろうか。まだ試していない。

調査記録

autodiscovery より、

Strategy:
1. Find all files and associate them from impl <-> test.
2. Run all tests.
3. Scan for failures.
4. Detect changes in ANY (ruby?. file, rerun all failures + changed files.
5. Until 0 defects, goto 3.
6. When 0 defects, goto 2.

って事らしい。

autodiscovery() より

Automatically find all potential autotest runner styles by searching your loadpath, vendor/plugins, and rubygems for "autotest/discover.rb".

ふんふん。

(discovery.rb) should register discovery procs with autotest using add_discovery.

autotest/discover.rb で discovery proc をセットする、と。

That proc should return one or more strings describing the user‘s current environment.
Those styles are then combined to dynamically invoke an autotest plugin to suite your environment.

これが runner-styles ってヤツですかね。

Autotest.add_discovery do
  styles if (cond)
end

こういう事か。

That plugin should define a subclass of Autotest with a corresponding name.

ですと。その下も見る。

Process:
1. All autotest/discover.rb files loaded.
2. Those procs determine your styles (eg ["rails", "rspec"]).
3. Require file by sorting styles and joining (eg ‘autotest/rails_rspec’).
4. Invoke run method on appropriate class (eg Autotest::RailsRspec.run).

理解。

Style の既存の種類と中身を探る。
ZenTest のファイル群を見ると camping.rb と rails.rb が見つかる。
何となく分かってきた。rails rspec プラグインも参考にしつつ、後は試す。

autotest/ の下は dicover.rb と stylename.rb ファイルになる。
stylename は文字通り。rspec.rb というファイル名にするとスタイル名は rspec になり、Autotest::Rspec クラスがある事が期待される。
つまり MyRspec スタイルを作りたかったらファイル名は autotest/my_rspec.rb とする。
これで vendor/plugins/(rspec|rspec_on_rails)/autotest の存在理由も分かった。