Quantcast
Channel: 情報と音楽 » bdd
Viewing all articles
Browse latest Browse all 2

Rails, RSpec, Spork(, Guard) で適切にクラスをリロード

$
0
0

もう少し簡潔に書けました。追記: Rails, RSpec, Spork(, Guard) で適切にクラスをリロード を参照。

Rails アプリケーションの開発時、spork と guard を使うと非常に効率がいいです。

この記事では spork 使用時にクラスを適切にリロードするための方法を紹介します (guard 関係ないけど、快適にテストできるとこまでのメモとして書いておきます)。spork と guard については、ググるか README みてください。

なお、ここではこの方法を確立した時点での最新リリースだった Rails 3.0.7 を想定してます。Rails 3.2 ではクラスリロードの方法が変わっているらしいのでそのままでは動かないかも。

spork / guard 使えるとこまで

ここはさらっと。

$ rails new blog --skip-test-unit $ cd blog # Gemfile group :development, :test do gem "rspec-rails" gem "spork" gem "guard-rspec" gem "guard-spork" # gem "growl" # spork で spec の実行完了時に growl で通知してくれる。好みで。 end $ bundle install $ rails g rspec:install $ spork --bootstrap # spec/spec_helper.rb # ENV["RAILS_ENV"] ||= 'test' 以下のコードを Spork.prefork do … end のブロック内に移動 $ guard init spork $ guard init rspec # Guardfile # spork で実行するよう :cli => "--drb" 追加 guard 'rspec', :version => 2, :cli => "--drb do

これで準備完了。

$ guard

で guard が起動するので、spec 下に適当な spec を書き、自動的に実行されることを確認する。

クラスのリロード

上記の手順を終えた状態では、クラスを書き換えても変更が反映されない。

クラスをリロードさせる方法は検索するといくつか見つかるが、うまくリロードできないケースがあったり、複数回クラスを load して、コールバック (before 何とかみたいなの) が重複して定義されるケースがあった。

いろいろ試した結果次の方法がよさそう。

# config/environment/test.rb Blog::Application.configure do # Spork 使用時はクラスをキャッシュしない # これは development のデフォルト設定と同じ if defined?(Spork) && Spork.using_spork? config.cache_classes = false else config.cache_classes = true end end # spec/spec_helper.rb Spork.each_run do if Spork.using_spork? # これがないと Spork 非使用時に失敗する # routes のリロード Blog::Application.reload_routes! # railties-3.0.7/lib/rails/application/bootstrap.rb よりコピペ # もともとは config.cache_classes が true のとき、リクエストごとに呼ばれる部分 # ここでは spec が実行されるごとに呼んでいる ActiveSupport::DescendantsTracker.clear ActiveSupport::Dependencies.clear # オブザーバが動いてないので、有効にする ActiveRecord::Base.instantiate_observers # machinist gem を利用してる場合、blueprints を再度読み直す # load "#{File.dirname(__FILE__)}/support/blueprints.rb" end end

基本的には development 環境でリクエストごとにクラスリロードしてるのと同じ方法なので、まともに動いてるようです。ただ、この方法だと controller のテストをする際にリクエストごとにクラスリロードしてしまって、遅くなるかも (未確認です)。

なお、上記の方法が本当に問題ないか不明なので、デプロイ前には spork も guard も使わない状態で全部テストすることをおすすめします。

おまけ

実際の開発時には Guardfile も一部オプションを変えてるので、一応紹介。

# Guardfile # 起動に時間がかかるとあきらめちゃうことがあるので 30 秒までは待つよう wait: 30 追加 guard 'spork', rspec_env: { 'RAILS_ENV' => 'test' }, wait: 30 do … # 上でも書いた cli: "--drb" のほか... # all_on_start: false - 起動時の spec 全部実行を無効に。時間かかるので。回帰テストは Jenkins さんにまかせます。 # all_after_pass: false - 実行した spec が全部パスした時の spec 全部実行を無効に。これも時間かかるので。 guard 'rspec', all_on_start: false, all_after_pass: false, version: 2, cli: "--drb" do …

それではみなさま良き Rails ライフを。


Viewing all articles
Browse latest Browse all 2

Trending Articles