Guard と Spork による Rails の自動テスト

シェアする

guard and spork

Ruby on Rails Tutorial の 3.6.2 - 3.6.3 に記載されているテストの自動化をほぼそのまま試しています。だいぶ説明を端折っているので原文を読んだほうが良いとおもいますが作業メモとしてここに残しておきます。

Learn Web Development with the Ruby on Rails Tutorial | Static Pages

一々 bundle exec rspec hogehoge.rb とかするのだるいから自動でしましょうってことでしょうか。Guard を使用して rails のテストを自動化してみます。

Sponsored Links

Guard の設定

Gemfile 編集して guard を使うように書き換えます

group :development, :test do
    gem 'sqlite3'
    gem 'rspec-rails', '2.13.0'
    gem 'guard-rspec', '2.5.0'
end<

書き換えたらインストールします。

$ bundle install

インストールがうまくいったら Guard の初期化を行います。

$ bundle exec guard init rspec
INFO - Writing new Guardfile to /home/ryomatsu/example/rortest/demo_app/Guardfile
INFO - rspec guard added to Guardfile, feel free to edit it

初期化したら Guardfile を編集します。

guard 'rspec', all_after_pass: false do
  ...
  # Custom Rails Tutorial specs
  watch(%r{^app/controllers/(.+)_(controller)\.rb$})  do |m|
    ["spec/routing/#{m[1]}_routing_spec.rb",
     "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb",
     "spec/acceptance/#{m[1]}_spec.rb",
     (m[1][/_pages/] ? "spec/requests/#{m[1]}_spec.rb" : 
                       "spec/requests/#{m[1].singularize}_pages_spec.rb")]
  end
  watch(%r{^app/views/(.+)/}) do |m|
    (m[1][/_pages/] ? "spec/requests/#{m[1]}_spec.rb" : 
                       "spec/requests/#{m[1].singularize}_pages_spec.rb")
  end
  watch(%r{^app/controllers/sessions_controller\.rb$}) do |m|
    "spec/requests/authentication_pages_spec.rb"
  end
  ...

:all_after_pass => false というのはテストにパスしたときに全部のテストを実行しない、というオプションの指定。全部テストしてたら結構時間かかるのでオフにしておきます。

書き換えたら実行してみる。

$ bundle exec guard
19:38:04 - INFO - Guard uses Tmux to send notifications.
19:38:04 - INFO - Guard uses TerminalTitle to send notifications.
19:38:04 - INFO - Guard::RSpec is running
19:38:04 - INFO - Running all specs

......

Finished in 0.49647 seconds
6 examples, 0 failures

ちゃんと動いてるようです。

Spork でテストのスピードアップ

bundle exec rspec したとき結構時間かかるヨネーってことで Spork を使ってテストを高速に走らすようにします。

Gemfile を編集して Spork を使用するように修正します。

group :development, :test do
    gem 'sqlite3'
    gem 'rspec-rails', '2.13.0'
    gem 'guard-rspec', '2.5.0'
    gem 'spork-rails', github: 'railstutorial/spork-rails'
    gem 'guard-spork', '1.5.0'
    gem 'childprocess', '0.3.6'
end

書き換えたら install

$ bundle install

そして実行, spork の設定を行います。

$ bundle exec spork --bootstrap
Using RSpec, Rails
Bootstrapping /home/ryomatsu/example/rortest/demo_app/spec/spec_helper.rb.
Done. Edit /home/ryomatsu/example/rortest/demo_app/spec/spec_helper.rb now with your favorite text editor and follow the instructions.

spork 無いとかいわれたら Gemfile に gem 'spork' とか書いて bundle install しなおすと動いたりします。

ちゃんと動いたら spec/spec_helper.rb を 編集します。Spork.prefork ブロックを以下のようにします。

Spork.prefork do
  ENV["RAILS_ENV"] ||= 'test'
  require File.expand_path("../../config/environment", __FILE__)
  require 'rspec/rails'
  require 'rspec/autorun'

  # Requires supporting ruby files with custom matchers and macros, etc,
  # in spec/support/ and its subdirectories.
  Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}

  # Checks for pending migrations before tests are run.
  # If you are not using ActiveRecord, you can remove this line.
  ActiveRecord::Migration.check_pending! if defined?(ActiveRecord::Migration)

  RSpec.configure do |config|
    # ## Mock Framework
    #
    # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
    #
    # config.mock_with :mocha
    # config.mock_with :flexmock
    # config.mock_with :rr

    # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
    config.fixture_path = "#{::Rails.root}/spec/fixtures"

    # If you're not using ActiveRecord, or you'd prefer not to run each of your
    # examples within a transaction, remove the following line or assign false
    # instead of true.
    config.use_transactional_fixtures = true

    # If true, the base class of anonymous controllers will be inferred
    # automatically. This will be the default behavior in future versions of
    # rspec-rails.
    config.infer_base_class_for_anonymous_controllers = false

    # Run specs in random order to surface order dependencies. If you find an
    # order dependency and want to debug it, you can fix the order by providing
    # the seed, which is printed after each run.
    #     --seed 1234
    config.order = "random"
    config.include Capybara::DSL
  end
end

これで準備ができました。

spork の実行

spork を実行する前に、spork を使わないときの実行時間を測っておいて、どのくらい高速化できるのかを調べれるようにします。

$ time bundle exec rspec spec/requests/static_pages_spec.rb
......

Finished in 0.21145 seconds
6 examples, 0 failures

Randomized with seed 65477

bundle exec rspec spec/requests/static_pages_spec.rb
5.94s user 0.35s system 99% cpu 6.329 total

5.94s ほどかかってますね。

次は spork を使ってみます。

$ bundle exec spork
Using RSpec, Rails
Preloading Rails environment
Loading Spork.prefork block...
Spork is ready and listening on 8989!

$ time bundle exec rspec spec/requests/static_pages_spec.rb --drb
......

Finished in 0.26917 seconds
6 examples, 0 failures

Randomized with seed 1167

bundle exec rspec spec/requests/static_pages_spec.rb --drb
1.90s user 0.10s system 80% cpu 2.494 total

3倍ほど早くなりました。

Guard と Spork を併用する

guard で spork を使うように設定します。まず初期化。

$ bundle exec guard init spork
INFO - spork guard added to Guardfile, feel free to edit it

そして Guardfile を spork を使用するように編集します。

guard 'spork', :cucumber_env => { 'RAILS_ENV' => 'test' }, 
                 :rspec_env    => { 'RAILS_ENV' => 'test' } do
    watch('config/application.rb')
    watch('config/environment.rb')
    watch('config/environments/test.rb')
    watch(%r{^config/initializers/.+\.rb$})
    watch('Gemfile')
    watch('Gemfile.lock')
    watch('spec/spec_helper.rb') { :rspec }
    watch('test/test_helper.rb') { :test_unit }
    watch(%r{features/support/}) { :cucumber }
end

編集したら guard を実行しましょう。

$ bundle exec guard
INFO - Guard uses Tmux to send notifications.
INFO - Guard uses TerminalTitle to send notifications.
INFO - Starting Spork for RSpec, Test::Unit
Using RSpec, Rails
Preloading Rails environment
Couldn't find a supported test framework that begins with 'testunit'

Supported test frameworks:
( ) Cucumber
(*) RSpec

Legend: ( ) - not detected in project   (*) - detected
Loading Spork.prefork block...
Spork is ready and listening on 8989!

これで Spork と Guard を使用した自動テスト環境が構築できました。が、なんだか Spork 自体の起動に失敗したとかいうエラー出たり出なかったりします。なんなんでしょう。ほっといたら直ったけど。

とりあえずこの状態で rails プロジェクト内のファイルを編集するとテストが実行されて、テストに失敗したら赤くなったり成功したら緑になったりします。tmux との連携もされてて良いですね。

Sponsored Link

シェアする

フォローする