autotest をカスタマイズする
- clear_mappings と二重定義について追記 @2008/04/12
「このファイルをセーブしたらこっちの spec 走らせたい!」と思ったので調べた。
ソースはこの辺
- ZenTest: http://zentest.rubyforge.org/ZenTest/
- autodiscovery(): http://zentest.rubyforge.org/ZenTest/classes/Autotest.html#M000010
結論
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 の存在理由も分かった。