[Ruby on Rails 3, Ruby on Rails 4] RSpec/Capybara: Spork でテストを高速化する

つづき。
「Ruby on Rails チュートリアル」をさわってみます。

[markdown]

> * [RSpec/Capybara: Gurad でテストを自動化する](https://www.d-wood.com/blog/2013/10/11_4834.html)
> * [RSpec/Capybara: rspec テストを試してみる](https://www.d-wood.com/blog/2013/10/11_4816.html)
> * [第3章 ほぼ静的なページの作成](http://railstutorial-ja.herokuapp.com/chapters/static-pages#top)

テストが開始されるまで時間がかかるのは、Railsの環境全体を読み込み直す必要があるから。
Spork は、これを解決することでテストの速度を向上させるとのこと。

> * [ASCIIcasts – “Episode 412 – Railsコマンドの高速化”](http://ja.asciicasts.com/episodes/412-fast-rails-commands)
> * [ASCIIcasts – “Episode 285 – Spork”](http://ja.asciicasts.com/episodes/285-spork)

## Gemfile

“`ruby
group :development, :test do
gem ‘sqlite3’, ‘~> 1.3.5’
gem ‘rspec-rails’, ‘~> 2.11.0’
gem ‘guard-rspec’
gem ‘guard-spork’
gem ‘childprocess’
gem ‘spork’
end
“`

## インストール

“`
% bundle install
% bundle exec spork –bootstrap
Using RSpec
Bootstrapping /Users/****/projects/sample_app/spec/spec_helper.rb.
Done. Edit /Users/****/projects/sample_app/spec/spec_helper.rb now with your favorite text editor and follow the instructions.
“`

## spec/spec_helper.rb

指示された spec/spec_helper.rb を設定します。

“`
% subl spec/spec_helper.rb
“`

ファイルを確認すると、Spork によって、2つのメソッドが追加されていました。

“`ruby
Spork.prefork do
# Loading more in this block will cause your tests to run faster. However,
# if you change any configuration or code from libraries loaded here, you’ll
# need to restart spork for it take effect.
end
Spork.each_run do
# This code will be run each time you run your specs.
end
“`

さらにファイルの中程から最後をみると、rspecの記述があるのでこれをコメントアウトして、Spork.prefork 内にコピーしてみました。

“`ruby
Spork.prefork do
ENV[“RAILS_ENV”] ||= ‘test’
require File.expand_path(“../../config/environment”, __FILE__)
require ‘rspec/rails’
require ‘rspec/autorun’
Dir[Rails.root.join(“spec/support/**/*.rb”)].each {|f| require f}
RSpec.configure do |config|
config.fixture_path = “#{::Rails.root}/spec/fixtures”
config.use_transactional_fixtures = true
config.infer_base_class_for_anonymous_controllers = false
config.order = “random”
end
end
“`

## Spork を起動する

以下でサーバが起動します。

“`
% bundle exec spork
Using RSpec
Preloading Rails environment
Loading Spork.prefork block…
Spork is ready and listening on 8989!
“`

### 速度の比較

–drb (“distributed Ruby” の略) オプションを追加することで、Spoke が利用されるので、速度を比較してみる。

“`
% time bundle exec rspec spec/requests/static_pages_spec.rb
……..
Finished in 0.35374 seconds
8 examples, 0 failures
Randomized with seed 44534
bundle exec rspec spec/requests/static_pages_spec.rb 3.24s user 0.74s system 97% cpu 4.085 total
% time bundle exec rspec spec/requests/static_pages_spec.rb –drb
……..
Finished in 0.38702 seconds
8 examples, 0 failures
Randomized with seed 48212
bundle exec rspec spec/requests/static_pages_spec.rb –drb 0.86s user 0.14s system 63% cpu 1.579 total
“`

CPU使用率が違うようですが、半分以下になっているようです。

> * [ASCIIcasts – “Episode 285 – Spork”](http://ja.asciicasts.com/episodes/285-spork)

## .rspec

Spork を標準で使えるよう、RSpecの設定に追加する。

“`
% subl .rspec
“`

“`
–color
–drb
“`

## GuardにSporkを導入する

GuardfileにSporkを追加します。

“`
% bundle exec guard init spork
23:37:33 – INFO – spork guard added to Guardfile, feel free to edit it
“`

“`
% subl Guardfile
“`

追加された以下のセクションを、RSpecセクションの上に移動します。

“`ruby
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.lock’)
watch(‘spec/spec_helper.rb’) { :rspec }
watch(‘test/test_helper.rb’) { :test_unit }
watch(%r{features/support/}) { :cucumber }
end
“`

さらにRSpecセクションに、`, :cli => ‘–drb’ `を追加します。

“`
guard ‘rspec’, :version => 2, :all_after_pass => false, :cli => ‘–drb’ do
“`

## GuardとSporkを同時に起動する

guardコマンドでGuardとSporkを同時に起動します。

“`
% bundle exec guard
23:49:58 – INFO – DEPRECATION WARNING: The :version option is deprecated. Only RSpec 2 is now supported.
23:49:58 – INFO – Guard is using TerminalNotifier to send notifications.
23:49:58 – INFO – Guard is using TerminalTitle to send notifications.
23:49:59 – INFO – Starting Spork for RSpec
Using RSpec
Preloading Rails environment
Loading Spork.prefork block…
Spork is ready and listening on 8989!
23:50:05 – INFO – Spork server for RSpec successfully started
23:50:05 – INFO – Guard::RSpec is running
23:50:05 – INFO – Running all specs
Running tests with args [“–drb”, “-f”, “progress”, “-r”, “/Users/****/projects/sample_app/vendor/bundle/ruby/2.0.0/gems/guard-rspec-2.5.4/lib/guard/rspec/formatter.rb”, “-f”, “Guard::RSpec::Formatter”, “–failure-exit-code”, “2”, “spec”]…
……..
Finished in 0.41932 seconds
8 examples, 0 failures
Randomized with seed 28763
Done.
23:50:08 – INFO – Guard is now watching at ‘/Users/****/projects/sample_app’
[1] guard(main)>
“`

## 補遺

> preforkで読み込むファイル (たとえばroutes.rb) が変更された場合、Sporkサーバーを再起動して新しいRailsの環境を再度読み込む必要があります。パスするはずのテストが失敗した場合は、Ctrl-CでSporkサーバーを停止して再起動してください。

### Spoke の設定

> * [ASCIIcasts – “Episode 285 – Spork”](http://ja.asciicasts.com/episodes/285-spork)
例えば FactoryGirl でひつようなもの。

“`ruby
Spork.each_run do
FactoryGirl.reload
end
“`

[/markdown]